博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux 线程 条件变量
阅读量:6383 次
发布时间:2019-06-23

本文共 5319 字,大约阅读时间需要 17 分钟。

一:条件变量
  直接上最基本的两个函数,先抓主要矛盾:
//等待条件int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restric mutex);1:把调用线程放到所等待条件的线程列表上2:对传进来已经加过锁的互斥量解锁3:线程进入休眠状态等待被唤醒注:1、2步为原子操作//通知条件int pthread_cond_signal(pthread_cond_t *cond);1:通知指定条件已经满足2:等待线程重新锁定互斥锁3:等待线程需要重新测试条件是否满足



 
二:生产者消费者 
  下面是一个多线程,生产者消费者问题,一个队列放暂存的数据:
1 #include 
2 #include
3 #include
4 #include
5 #include
6 7 using std::cout; 8 using std::endl; 9 using std::queue;10 11 #define N 10012 #define ST 1013 14 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;15 pthread_cond_t ready = PTHREAD_COND_INITIALIZER;16 17 queue
que;18 19 void* threadProducer(void* arg)20 {21 while(true)22 {23 sleep(rand() % ST);24 25 cout << "Produce try in...\n";26 pthread_mutex_lock(&lock);27 cout << "Produce in!\n";28 int source = rand() % N;29 cout << "Produce " << source << endl;30 que.push(source);31 pthread_mutex_unlock(&lock);32 cout << "Produce out\n";33 34 pthread_cond_signal(&ready);35 }36 }37 38 void* threadConsumer(void* arg)39 {40 while(true)41 {42 sleep(rand() % ST);43 44 cout << "Consum try in...\n";45 pthread_mutex_lock(&lock);46 cout << "Consum in!\n";47 while(que.empty())48 {49 pthread_cond_wait(&ready, &lock);50 cout << "Consum from sleep\n";51 }52 cout << "Consum " << que.front() << endl;53 que.pop();54 pthread_mutex_unlock(&lock);55 cout << "Consum out\n\n";56 }57 }58 59 int main(void)60 {61 pthread_t tProducer, tConsumer; 62 pthread_create(&tProducer, NULL, threadProducer, NULL);63 pthread_create(&tConsumer, NULL, threadConsumer, NULL);64 65 pthread_join(tProducer, NULL);66 pthread_join(tConsumer, NULL);67 68 exit(0);69 }
生消

看到倒数的三四行,消费者进去了,发现没有数据了,则睡眠了,然后生产者进去生产了。



 
三:打印的例子
  下面是一个多线程的小例子,线程1打印非3的倍数,线程2打印3的倍数:
#include 
#include
#include
#include
using std::cout;using std::endl;pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t ready = PTHREAD_COND_INITIALIZER;int data = 0;void* threadProducer(void* arg){ int i; for(i = 1; i < 22; i++) { sleep(1); if(i % 3 != 0) { cout << "thread1:" << i << endl; } else { pthread_mutex_lock(&lock); data = i; pthread_mutex_unlock(&lock); pthread_cond_signal(&ready); } }}void* threadConsumer(void* arg){ while(true) { pthread_mutex_lock(&lock); while(data == 0) //no data pthread_cond_wait(&ready, &lock); cout <<"thread2:" << data << endl; if(data == 21) break; else data = 0; //empty data pthread_mutex_unlock(&lock); }}int main(void){ pthread_t tProducer, tConsumer; pthread_create(&tProducer, NULL, threadProducer, NULL); pthread_create(&tConsumer, NULL, threadConsumer, NULL); pthread_join(tProducer, NULL); pthread_join(tConsumer, NULL); exit(0);}
3打印

  程序大致这样:线程1中的循环,如果i不是3的倍数就自己打印了,如果是的话,把这个数放到一个地方(由于这个地方可以被线程2发现,所以要加锁访问),然后唤醒等待数据的线程2(如果线程2还没有在等待,那么这个唤醒则丢失,这是个bug,见下),线程2被唤醒后,消费了这个3的倍数,清空数据区。

  上面提到,如果唤醒线程2的消息没有被收到,则bug。看下面的代码,也就多了38一行,让线程2睡了一会,就在它睡觉的那么一会,线程1把3的倍数往那里一扔就走了,自己再继续下两个不是3倍数的数字,这就直接输出了下面两个数字,又到了3倍数,又扔过去覆盖了之前数字:
1 #include 
2 #include
3 #include
4 #include
5 6 using std::cout; 7 using std::endl; 8 9 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;10 pthread_cond_t ready = PTHREAD_COND_INITIALIZER;11 12 int data = 0;13 14 void* threadProducer(void* arg)15 {16 int i;17 for(i = 1; i < 22; i++)18 { 19 sleep(1);20 21 if(i % 3 != 0)22 {23 cout << "thread1:" << i << endl;24 }25 else26 {27 pthread_mutex_lock(&lock);28 data = i;29 pthread_mutex_unlock(&lock);30 31 pthread_cond_signal(&ready);32 } 33 }34 }35 36 void* threadConsumer(void* arg)37 {38 sleep(20);39 while(true)40 {41 pthread_mutex_lock(&lock);42 while(data == 0) //no data43 pthread_cond_wait(&ready, &lock);44 cout <<"thread2:" << data << endl;45 if(data == 21)46 break;47 else48 data = 0; //empty data49 pthread_mutex_unlock(&lock);50 }51 }52 53 int main(void)54 {55 pthread_t tProducer, tConsumer; 56 pthread_create(&tProducer, NULL, threadProducer, NULL);57 pthread_create(&tConsumer, NULL, threadConsumer, NULL);58 59 pthread_join(tProducer, NULL);60 pthread_join(tConsumer, NULL);61 62 exit(0);63 }
bug




 
四:总结  
  从上面可以总结出下面的条件变量的生产者消费者代码模型:
//下面是生产者pthread_mutex_lock(&lock);    //加锁访问临界区/*在这里生产数据*/pthread_mutex_unlock(&lock);    //解锁    pthread_cond_signal(&ready);    //通知消费者//下面是消费者pthread_mutex_lock(&lock);    //加锁访问临界区while(没有待消费数据)        pthread_cond_wait(&ready, &lock);    //睡在这里,等待被唤醒/*被叫醒了,在这里消费数据*/pthread_mutex_unlock(&lock);    //解锁

转载于:https://www.cnblogs.com/jiayith/p/3876624.html

你可能感兴趣的文章
Nginx 安装
查看>>
php GD库
查看>>
项目管理
查看>>
隐私政策
查看>>
二分搜索树
查看>>
[折半查找]排序数组中某个元素出现次数
查看>>
【11-01】Sublime text 学习笔记
查看>>
.wav file research
查看>>
Link-Cut-Tree题目泛做(为了对应自己的课件)
查看>>
多态-典型用法
查看>>
学习笔记之pandas Foundations | DataCamp
查看>>
C++编程练习(14)-------“单例模式”的实现
查看>>
css学习_标签的显示模式
查看>>
《架构之美》摘录二
查看>>
JDK8 Lamdba表达式转换成Map,value为null问题
查看>>
python基础===正则表达式(转)
查看>>
如何让你的SQL运行得更快
查看>>
NewLife.XCode 上手指南(五) 复杂查询
查看>>
_02特性 给方法加上注释 或者停用
查看>>
java2 -宏观了解
查看>>