首页 > 代码库 > Linux 线程 条件变量

Linux 线程 条件变量

<style></style>
  下面是一个多线程,生产者消费者问题,一个队列放暂存的数据:
 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);}
3打印

  程序大致这样:线程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 }
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);    //解锁