1.pthread_cond_wait()会干两件事
a).阻塞本线程
b).释放锁,等待singal或者broadcast,条件变量改变之后,加锁。唤醒线程
以上a+b是一个原子操作
2.既然wait已经释放锁了,那么如果signal在加解锁mutex中间的话,会一直等到释放锁了,wait才能得到条件变量修改的信息。
也就是说wait不仅等signal或broadcast,也会等pthread_mutex_unlock。只有两个条件都满足了才会继续执行
3.本例子中的singal是放在加解锁之间的,这样也不会损失性能(对linux是这样),而不会出现race condition,否则放在mutex unlock之后,可能会有别的线程抢占mutex
4.本例子中,0=
5.在consume和produce函数中,每次加/减完毕都会signal
-
#include <stdio.h>
-
#include <pthread.h>
-
#include <iostream>
-
using namespace std;
-
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
pthread_cond_t event = PTHREAD_COND_INITIALIZER;
-
-
int num = 0;
-
int countP = 0;
-
-
bool flag=false;
-
-
void *produce(void *p)
-
{
-
int count = 0;
-
while(!flag)
-
{
-
pthread_mutex_lock(&lock);
-
while(num==100)
-
{
-
pthread_cond_wait(&event,&lock);
-
}
-
num++;
-
pthread_cond_signal(&event);
-
pthread_mutex_unlock(&lock);
-
count++;
-
}
-
return (void*)count;
-
}
-
-
void *cosume(void *p)
-
{
-
int count = 0;
-
while(!flag)
-
{
-
pthread_mutex_lock(&lock);
-
while(num==0)
-
{
-
pthread_cond_wait(&event, &lock);
-
}
-
num--;
-
countP++;
-
if(countP==100000)
-
flag = true;
-
pthread_cond_signal(&event);
-
pthread_mutex_unlock(&lock);
-
count++;
-
}
-
return (void*)count;
-
}
-
-
int main()
-
{
-
pthread_t tid[4];
-
pthread_create(tid+0, NULL, produce, NULL);
-
pthread_create(tid+1, NULL, produce, NULL);
-
pthread_create(tid+2, NULL, cosume, NULL);
-
pthread_create(tid+3, NULL, cosume, NULL);
-
-
int countP;
-
int countM;
-
pthread_join(tid[0], (void**)&countM);
-
cout<<"producer 0 "<<" "<<countM<<endl;
-
pthread_join(tid[1], (void**)&countM);
-
cout<<"producer 1 "<<" "<<countM<<endl;
-
pthread_join(tid[2], (void**)&countM);
-
cout<<"consumer 0 "<<" "<<countM<<endl;
-
pthread_join(tid[3], (void**)&countM);
-
cout<<"consumer 1 "<<" "<<countM<<endl;
-
-
-
return 0;
-
}
以下是对上面的另一个实现版本,改动如下:
1.不是每次都signal,而是有判断,才signal;
2.其实1中的signal我都改为了broadcast;
3.为了符合每次循环只有一次对num的操作,添加了两个bool变量
其中使用了broadcast,不知道为什么使用signal不可。不过unp上的一段话可以作为参看。
考虑条件信号量单播发送和广播发送的一种候选(且更为安全的)方式市坚持使用广播发送。如果所有的等待者代码都编写确切,只有一个等待者需要唤醒,而且唤醒哪一个无关紧要,那么可以使用为这些情况而优化的单播。所有其他情况都应該使用广播发送。
-
#include <stdio.h>
-
#include <pthread.h>
-
#include <iostream>
-
using namespace std;
-
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
-
pthread_cond_t event = PTHREAD_COND_INITIALIZER;
-
-
int num = 0;
-
int countP = 0;
-
-
bool flag=false;
-
-
void *produce(void *p)
-
{
-
int count = 0;
-
while(!flag)
-
{
-
pthread_mutex_lock(&lock);
-
while(num==100)
-
{
-
cout<<"producer num==100"<<endl;
-
pthread_cond_wait(&event,&lock);
-
}
-
-
bool empty = false;
-
if(num==0)
-
{
-
empty=true;
-
num++;
-
cout<<"producer num==0"<<endl;
-
pthread_cond_broadcast(&event);
-
}
-
if(!empty)
-
num++;
-
pthread_mutex_unlock(&lock);
-
count++;
-
}
-
return (void*)count;
-
}
-
-
void *cosume(void *p)
-
{
-
int count = 0;
-
while(!flag)
-
{
-
pthread_mutex_lock(&lock);
-
while(num==0)
-
{
-
cout<<"consume num==0"<<endl;
-
pthread_cond_wait(&event, &lock);
-
}
-
countP++;
-
if(countP==1000)
-
flag = true;
-
bool full = false;
-
if(num==100)
-
{
-
full = true;
-
num--;
-
cout<<"consume num==100"<<endl;
-
pthread_cond_broadcast(&event);
-
}
-
if(!full)
-
num--;
-
pthread_mutex_unlock(&lock);
-
count++;
-
}
-
return (void*)count;
-
}
-
-
int main()
-
{
-
pthread_t tid[4];
-
pthread_create(tid+0, NULL, produce, NULL);
-
sleep(1);
-
pthread_create(tid+1, NULL, produce, NULL);
-
sleep(1);
-
pthread_create(tid+2, NULL, cosume, NULL);
-
pthread_create(tid+3, NULL, cosume, NULL);
-
-
int countP;
-
int countM;
-
pthread_join(tid[0], (void**)&countM);
-
cout<<"producer 0 "<<" "<<countM<<endl;
-
pthread_join(tid[1], (void**)&countM);
-
cout<<"producer 1 "<<" "<<countM<<endl;
-
pthread_join(tid[2], (void**)&countM);
-
cout<<"consumer 0 "<<" "<<countM<<endl;
-
pthread_join(tid[3], (void**)&countM);
-
cout<<"consumer 1 "<<" "<<countM<<endl;
-
-
-
return 0;
-
}
阅读(3556) | 评论(0) | 转发(0) |