首页 > 代码库 > Linux 线程 条件变量
Linux 线程 条件变量
<style></style>生消看到倒数的三四行,消费者进去了,发现没有数据了,则睡眠了,然后生产者进去生产了。
3打印bug
下面是一个多线程,生产者消费者问题,一个队列放暂存的数据:
1 #include <iostream> 2 #include <queue> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <pthread.h> 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<int> 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 <iostream>#include <stdlib.h>#include <unistd.h>#include <pthread.h>using std::cout;using std::endl;pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t ready = PTHREAD_COND_INITIALIZER;int data = http://www.mamicode.com/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 =http://www.mamicode.com/= 0) //no data pthread_cond_wait(&ready, &lock); cout <<"thread2:" << data << endl; if(data =http://www.mamicode.com/= 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);}
程序大致这样:线程1中的循环,如果i不是3的倍数就自己打印了,如果是的话,把这个数放到一个地方(由于这个地方可以被线程2发现,所以要加锁访问),然后唤醒等待数据的线程2(如果线程2还没有在等待,那么这个唤醒则丢失,这是个bug,见下),线程2被唤醒后,消费了这个3的倍数,清空数据区。
上面提到,如果唤醒线程2的消息没有被收到,则bug。看下面的代码,也就多了38一行,让线程2睡了一会,就在它睡觉的那么一会,线程1把3的倍数往那里一扔就走了,自己再继续下两个不是3倍数的数字,这就直接输出了下面两个数字,又到了3倍数,又扔过去覆盖了之前数字:
1 #include <iostream> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <pthread.h> 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 = http://www.mamicode.com/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 =http://www.mamicode.com/ 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 =http://www.mamicode.com/= 0) //no data43 pthread_cond_wait(&ready, &lock);44 cout <<"thread2:" << data << endl;45 if(data =http://www.mamicode.com/= 21)46 break;47 else48 data = http://www.mamicode.com/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 }
从上面可以总结出下面的条件变量的生产者消费者代码模型:
//下面是生产者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); //解锁
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。