一:条件变量
  直接上最基本的两个函数,先抓主要矛盾:
//等待条件
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 <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 100
12 #define ST 10
13 
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 }
生消

Linux 线程 条件变量

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



 
三:打印的例子
  下面是一个多线程的小例子,线程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 = 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打印

Linux 线程 条件变量

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

相关文章: