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=<num<=100,两个线程负责加,两个线程负责减,当减操作完成1000次时,四个线程均停止。每个线程返回自己的对num的操作次数
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;
- }
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。