条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行
应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信号的产生
主要函数有两个:
1)等待条件
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
2)发送条件信号
int pthread_cond_signal(pthread_cond_t *cond);
请参考:
http://www.diybl.com/course/3_program/c++/cppjs/20110518/555794.html
http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part3/
编译:
gcc -o pthread pthread.c -lpthread
- /*单个生产者和单个消费者*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <pthread.h>
- #define BUFFER_SIZE 5 //产品库存大小
- #define PRODUCT_CNT 50 //产品生产总数
- struct product_cons
- {
- int buffer[BUFFER_SIZE]; //生产产品值
- pthread_mutex_t lock; //互斥锁 volatile int
- int readpos, writepos; //读写位置
- pthread_cond_t notempty; //条件变量,非空
- pthread_cond_t notfull; //非满
- }buffer;
- void init(struct product_cons *p)
- {
- pthread_mutex_init(&p->lock, NULL); //互斥锁
- pthread_cond_init(&p->notempty, NULL); //条件变量
- pthread_cond_init(&p->notfull, NULL); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- }
- void fini(struct product_cons *p)
- {
- pthread_mutex_destroy(&p->lock); //互斥锁
- pthread_cond_destroy(&p->notempty); //条件变量
- pthread_cond_destroy(&p->notfull); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- }
- void cleanup_handler(void *arg)
- {
- printf("cleanup_handler exec!\n");
- pthread_mutex_t *lock = (pthread_mutex_t*)arg;
- pthread_mutex_unlock(lock); //解锁
- }
- //存储 一个数据 到 bufferr
- void put(struct product_cons *p, int data) //输入产品子函数
- {
- pthread_mutex_lock(&p->lock); //上锁
- /*等待,直到 buffer 不为 满*/
- while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满
- {
- printf("producer wait for not full\n");
- pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待
- //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号
- //如果,消费者发送了 signal 信号,表示有了 空闲
- }
- p->buffer[p->writepos] = data; //写数据
- p->writepos++;
- if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回
- p->writepos = 0;
- pthread_cond_signal(&p->notempty); //发送有数据信号
- pthread_mutex_unlock(&p->lock); //解锁
- }
- //读,移除 一个数据 从 buffer
- int get(struct product_cons *p)
- {
- int data = 0;
- pthread_mutex_lock(&p->lock);
- /*等待,直到不为空*/
- while(p->writepos == p->readpos)
- {
- printf("consumer wait for not empty\n");
- pthread_cond_wait(&p->notempty,&p->lock);
- }
- /*读 一个 数据*/
- data = p->buffer[p->readpos];
- p->readpos++;
- if(p->readpos >= BUFFER_SIZE) //如果读到 尾
- p->readpos = 0;
- pthread_cond_signal(&p->notfull);
- pthread_mutex_unlock(&p->lock);
- return data;
- }
- void *producer(void *data) //子线程 ,生产
- {
- int n;
- for(n = 1; n <= 50; ++n) //生产 50 个产品
- {
- sleep(1);
- printf("put the %d product\n",n);
- put(&buffer,n);
- }
- printf("producer stopped\n");
- return NULL;
- }
- void *consumer(void *data)
- {
- static int cnt = 0;
- while(1)
- {
- sleep(2);
- printf("get the %d product\n", get(&buffer));
- if(++cnt == PRODUCT_CNT)
- break;
- }
- printf("consumer stopped\n");
- return NULL;
- }
- int main(int argc, char *argv[])
- {
- pthread_t th_a,th_b;
- void *retval;
- init(&buffer);
- pthread_create(&th_a, NULL, producer, 0);
- pthread_create(&th_b, NULL, consumer, 0);
- pthread_join(th_a, &retval);
- pthread_join(th_b, &retval);
- fini(&buffer);
- return 0;
- }
- /*多个生产者和单个消费者*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <pthread.h>
- #define BUFFER_SIZE 5 //产品库存大小
- #define PRODUCT_CNT 50 //产品生产总数
- struct product_cons
- {
- int buffer[BUFFER_SIZE]; //生产产品值
- pthread_mutex_t lock; //互斥锁,控制buffer
- int readpos, writepos; //读写位置
- pthread_cond_t notempty; //条件变量,非空
- pthread_cond_t notfull; //非满
- pthread_mutex_t lock2; //互斥锁,控制cnt
- int cnt; //完成生产产品数量
- }buffer;
- void init(struct product_cons *p)
- {
- pthread_mutex_init(&p->lock, NULL); //互斥锁
- pthread_cond_init(&p->notempty, NULL); //条件变量
- pthread_cond_init(&p->notfull, NULL); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- pthread_mutex_init(&p->lock2, NULL);
- p->cnt = 0;
- }
- void fini(struct product_cons *p)
- {
- pthread_mutex_destroy(&p->lock); //互斥锁
- pthread_cond_destroy(&p->notempty); //条件变量
- pthread_cond_destroy(&p->notfull); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- pthread_mutex_destroy(&p->lock2);
- p->cnt = 0;
- }
- //存储 一个数据 到 bufferr
- void put(struct product_cons *p, int data) //输入产品子函数
- {
- pthread_mutex_lock(&p->lock); //上锁
- /*等待,直到 buffer 不为 满*/
- while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满
- {
- printf("producer wait for not full\n");
- pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待
- //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号
- //如果,消费者发送了 signal 信号,表示有了 空闲
- }
- p->buffer[p->writepos] = data; //写数据
- p->writepos++;
- if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回
- p->writepos = 0;
- pthread_cond_signal(&p->notempty); //发送有数据信号
- pthread_mutex_unlock(&p->lock); //解锁
- }
- //读,移除 一个数据 从 buffer
- int get(struct product_cons *p)
- {
- int data = 0;
- pthread_mutex_lock(&p->lock);
- /*等待,直到不为空*/
- while(p->writepos == p->readpos)
- {
- printf("consumer wait for not empty\n");
- pthread_cond_wait(&p->notempty,&p->lock);
- }
- /*读 一个 数据*/
- data = p->buffer[p->readpos];
- p->readpos++;
- if(p->readpos >= BUFFER_SIZE) //如果读到 尾
- p->readpos = 0;
- pthread_cond_signal(&p->notfull);
- pthread_mutex_unlock(&p->lock);
- return data;
- }
- void *producer(void *data) //子线程 ,生产
- {
- int flag = -1;
- while(1)
- {
- pthread_mutex_lock(&buffer.lock2);
- if(buffer.cnt < PRODUCT_CNT)
- {
- ++buffer.cnt;
- printf("%s put the %d product\n", (char*)data, buffer.cnt);
- put(&buffer, buffer.cnt);
- }
- else
- flag = 0;
- pthread_mutex_unlock(&buffer.lock2);
- if(!flag)
- break;
- sleep(2);
- }
- printf("%s producer stopped\n", (char*)data);
- return NULL;
- }
- void *consumer(void *data)
- {
- int d = 0;
- while(1)
- {
- sleep(1);
- d = get(&buffer);
- printf("get the %d product\n",d);
- if(d == PRODUCT_CNT)
- break;
- }
- printf("consumer stopped\n");
- return NULL;
- }
- int main(int argc, char *argv[])
- {
- pthread_t th_a[3],th_b;
- void *retval;
- init(&buffer);
- pthread_create(&th_a[0], NULL, producer, (void*)"th_a[0]");
- pthread_create(&th_a[1], NULL, producer, (void*)"th_a[1]");
- pthread_create(&th_a[2], NULL, producer, (void*)"th_a[2]");
- pthread_create(&th_b, NULL, consumer, 0);
- pthread_join(th_a[0], &retval);
- pthread_join(th_a[1], &retval);
- pthread_join(th_a[2], &retval);
- pthread_join(th_b, &retval);
- fini(&buffer);
- return 0;
- }
- /*单个生产者和多个消费者*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <pthread.h>
- #define BUFFER_SIZE 5 //产品库存大小
- #define PRODUCT_CNT 50 //产品生产总数
- struct product_cons
- {
- int buffer[BUFFER_SIZE]; //生产产品值
- pthread_mutex_t lock; //互斥锁 volatile int
- int readpos, writepos; //读写位置
- pthread_cond_t notempty; //条件变量,非空
- pthread_cond_t notfull; //非满
- pthread_mutex_t lock2; //互斥锁,控制cnt
- int cnt; //获得生产产品数量
- }buffer;
- void init(struct product_cons *p)
- {
- pthread_mutex_init(&p->lock, NULL); //互斥锁
- pthread_cond_init(&p->notempty, NULL); //条件变量
- pthread_cond_init(&p->notfull, NULL); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- pthread_mutex_init(&p->lock2, NULL);
- p->cnt = 0;
- }
- void fini(struct product_cons *p)
- {
- pthread_mutex_destroy(&p->lock); //互斥锁
- pthread_cond_destroy(&p->notempty); //条件变量
- pthread_cond_destroy(&p->notfull); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- pthread_mutex_destroy(&p->lock2);
- p->cnt = 0;
- }
- //存储 一个数据 到 bufferr
- void put(struct product_cons *p, int data) //输入产品子函数
- {
- pthread_mutex_lock(&p->lock); //上锁
- /*等待,直到 buffer 不为 满*/
- while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满
- {
- printf("producer wait for not full\n");
- pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待
- //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号
- //如果,消费者发送了 signal 信号,表示有了 空闲
- }
- p->buffer[p->writepos] = data; //写数据
- p->writepos++;
- if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回
- p->writepos = 0;
- pthread_cond_signal(&p->notempty); //发送有数据信号
- pthread_mutex_unlock(&p->lock); //解锁
- }
- //读,移除 一个数据 从 buffer
- int get(struct product_cons *p)
- {
- int data = 0;
- pthread_mutex_lock(&p->lock);
- /*等待,直到不为空*/
- while(p->writepos == p->readpos)
- {
- printf("consumer wait for not empty\n");
- pthread_cond_wait(&p->notempty,&p->lock);
- }
- /*读 一个 数据*/
- data = p->buffer[p->readpos];
- p->readpos++;
- if(p->readpos >= BUFFER_SIZE) //如果读到 尾
- p->readpos = 0;
- pthread_cond_signal(&p->notfull);
- pthread_mutex_unlock(&p->lock);
- return data;
- }
- void *producer(void *data) //子线程 ,生产
- {
- int n;
- for(n = 1; n <= PRODUCT_CNT; ++n) //生产 50 个产品
- {
- sleep(1);
- printf("put the %d product\n",n);
- put(&buffer, n);
- }
- printf("producer stopped\n");
- return NULL;
- }
- void *consumer(void *data)
- {
- int flag = -1;
- while(1)
- {
- pthread_mutex_lock(&buffer.lock2);
- if(buffer.cnt < PRODUCT_CNT)
- {
- printf("%s get the %d product\n", (char*)data, get(&buffer));
- ++buffer.cnt;
- }
- else
- flag = 0;
- pthread_mutex_unlock(&buffer.lock2);
- if(!flag)
- break;
- sleep(2);
- }
- printf("%s consumer stopped\n", (char*)data);
- return NULL;
- }
- int main(int argc, char *argv[])
- {
- pthread_t th_a,th_b[3];
- void *retval;
- init(&buffer);
- pthread_create(&th_a, NULL, producer, 0);
- pthread_create(&th_b[0], NULL, consumer, (void*)"th_b[0]");
- pthread_create(&th_b[1], NULL, consumer, (void*)"th_b[1]");
- pthread_create(&th_b[2], NULL, consumer, (void*)"th_b[2]");
- pthread_join(th_a, &retval);
- pthread_join(th_b[0], &retval);
- pthread_join(th_b[1], &retval);
- pthread_join(th_b[2], &retval);
- fini(&buffer);
- return 0;
- }
- /*多个生产者和多个消费者*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <pthread.h>
- #define BUFFER_SIZE 5 //产品库存大小
- #define PRODUCT_CNT 50 //产品生产总数
- struct product_cons
- {
- int buffer[BUFFER_SIZE]; //生产产品值
- pthread_mutex_t lock; //互斥锁 volatile int
- int readpos, writepos; //读写位置
- pthread_cond_t notempty; //条件变量,非空
- pthread_cond_t notfull; //非满
- pthread_mutex_t lock2; //互斥锁,控制cnt_p
- int cnt_p; //完成生产产品数量
- pthread_mutex_t lock3; //互斥锁,控制cnt_c
- int cnt_c; //获得生产产品数量
- }buffer;
- void init(struct product_cons *p)
- {
- pthread_mutex_init(&p->lock, NULL); //互斥锁
- pthread_cond_init(&p->notempty, NULL); //条件变量
- pthread_cond_init(&p->notfull, NULL); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- pthread_mutex_init(&p->lock2, NULL);
- p->cnt_p = 0;
- pthread_mutex_init(&p->lock3, NULL);
- p->cnt_c = 0;
- }
- void fini(struct product_cons *p)
- {
- pthread_mutex_destroy(&p->lock); //互斥锁
- pthread_cond_destroy(&p->notempty); //条件变量
- pthread_cond_destroy(&p->notfull); //条件变量
- p->readpos = 0; //读写位置
- p->writepos = 0;
- pthread_mutex_destroy(&p->lock2);
- p->cnt_p = 0;
- pthread_mutex_destroy(&p->lock3);
- p->cnt_c = 0;
- }
- //存储 一个数据 到 bufferr
- void put(struct product_cons *p, int data) //输入产品子函数
- {
- pthread_mutex_lock(&p->lock); //上锁
- /*等待,直到 buffer 不为 满*/
- while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满
- {
- printf("producer wait for not full\n");
- pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待
- //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号
- //如果,消费者发送了 signal 信号,表示有了 空闲
- }
- p->buffer[p->writepos] = data; //写数据
- p->writepos++;
- if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回
- p->writepos = 0;
- pthread_cond_signal(&p->notempty); //发送有数据信号
- pthread_mutex_unlock(&p->lock); //解锁
- }
- //读,移除 一个数据 从 buffer
- int get(struct product_cons *p)
- {
- int data = 0;
- pthread_mutex_lock(&p->lock);
- /*等待,直到不为空*/
- while(p->writepos == p->readpos)
- {
- printf("consumer wait for not empty\n");
- pthread_cond_wait(&p->notempty,&p->lock);
- }
- /*读 一个 数据*/
- data = p->buffer[p->readpos];
- p->readpos++;
- if(p->readpos >= BUFFER_SIZE) //如果读到 尾
- p->readpos = 0;
- pthread_cond_signal(&p->notfull);
- pthread_mutex_unlock(&p->lock);
- return data;
- }
- void *producer(void *data) //子线程 ,生产
- {
- int flag = -1;
- while(1)
- {
- pthread_mutex_lock(&buffer.lock2);
- if(buffer.cnt_p < PRODUCT_CNT)
- {
- ++buffer.cnt_p;
- printf("%s put the %d product\n", (char*)data, buffer.cnt_p);
- put(&buffer, buffer.cnt_p);
- }
- else
- flag = 0;
- pthread_mutex_unlock(&buffer.lock2);
- if(!flag)
- break;
- sleep(2);
- }
- printf("%s producer stopped\n", (char*)data);
- return NULL;
- }
- void *consumer(void *data)
- {
- int flag = -1;
- while(1)
- {
- pthread_mutex_lock(&buffer.lock3);
- if(buffer.cnt_c < PRODUCT_CNT)
- {
- printf("%s get the %d product\n", (char*)data, get(&buffer));
- ++buffer.cnt_c;
- }
- else
- flag = 0;
- pthread_mutex_unlock(&buffer.lock3);
- if(!flag)
- break;
- sleep(2);
- }
- printf("%s consumer stopped\n", (char*)data);
- return NULL;
- }
- int main(int argc, char *argv[])
- {
- pthread_t th_a[3],th_b[3];
- void *retval;
- init(&buffer);
- pthread_create(&th_a[0], NULL, producer, (void*)"th_a[0]");
- pthread_create(&th_a[1], NULL, producer, (void*)"th_a[1]");
- pthread_create(&th_a[2], NULL, producer, (void*)"th_a[2]");
- pthread_create(&th_b[0], NULL, consumer, (void*)"th_b[0]");
- pthread_create(&th_b[1], NULL, consumer, (void*)"th_b[1]");
- pthread_create(&th_b[2], NULL, consumer, (void*)"th_b[2]");
- pthread_join(th_a[0], &retval);
- pthread_join(th_a[1], &retval);
- pthread_join(th_a[2], &retval);
- pthread_join(th_b[0], &retval);
- pthread_join(th_b[1], &retval);
- pthread_join(th_b[2], &retval);
- fini(&buffer);
- return 0;
- }