用条件变量来解决生产者消费者问题
来源:互联网 发布:数据库事务一致性 编辑:程序博客网 时间:2024/04/28 07:04
在上一篇文章中,我使用了匿名信号量
什么是条件变量?
我们可以设想一个场景:线程A需要某个条件成立才能继续执行,否则一直等待下去,而线程B执行过程中使线程的执行条件成立,并且唤醒A。
举个例子,在生产者消费者模型中,消费者如果看到缓冲区为空时,就等待,而生产者往缓冲区添加完数据后,唤醒消费者。
其中这个场景中,可以POSIX的条件变量来实现。
以下是条件变量所需要的函数
pthread_cond_initpthread_cond_destroypthread_cond_waitpthread_cond_signalpthread_cond_broadcast
这里大家就百度怎么用,或者在Linux中用man 3 pthread_cond_***的方法也行。
其中重点讲一下的是 pthread_cond_wait这个函数。
条件变量是要和互斥量配合使用的,而pthread_cond_wait的搭配互斥量后是执行者三步操作。
第一,条件不成立时,释放互斥量(将互斥量解锁)。
第二,阻塞自己,让别的线程开始执行。
第三,当被其他的线程唤醒时,重新获得互斥量(重新将互斥量加锁),并执行后续代码。
掌握了这个之后,就来说下条件变量的使用规范。
第一,等待条件代码
pthread_mutex_lock(&mutex);while (条件为假) pthread_cond_wait(cond, mutex);修改条件;pthread_mutex_unlock(&mutex);
第二,修改条件代码
pthread_mutex_lock(&mutex);设置条件为真pthread_cond_signal(cond);pthread_mutex_unlock(&mutex);
在这里的一个难点是,第一段条件等待代码为什么不用if而用while呢?在man 3 pthread_cond_wait 之后发现这样一段话
If a signal is delivered to a thread waiting for a condition variable, upon return from the signal handler the thread resumes waiting for the condition variable as if it was not interrupted, or it shall return zero due to spurious wakeup.
也就是说,唤醒条件的信号,可以唤醒多个线程,但是只能允许一个信号访问,也就是说,因此等待线程需要不断的用while轮询一直到达到条件了才行。
好了,讲了这么多我们用它来做个生产者消费者实例吧。
#include <unistd.h>#include <sys/types.h>#include <pthread.h>#include <semaphore.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#define ERR_EXIT(m) \ do \ { \ perror(m); \ exit(EXIT_FAILURE); \ } while(0)#define CONSUMERS_COUNT 2#define PRODUCERS_COUNT 1pthread_mutex_t g_mutex;pthread_cond_t g_cond;pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT];int nready = 0;void *consume(void *arg){ int num = (int)arg; while (1) { pthread_mutex_lock(&g_mutex); while (nready == 0) { printf("%d begin wait a condtion ...\n", num); pthread_cond_wait(&g_cond, &g_mutex); } printf("%d end wait a condtion ...\n", num); printf("%d begin consume product ...\n", num); --nready; printf("%d end consume product ...\n", num); pthread_mutex_unlock(&g_mutex); sleep(1); } return NULL;}void *produce(void *arg){ int num = (int)arg; while (1) { pthread_mutex_lock(&g_mutex); printf("%d begin produce product ...\n", num); ++nready; printf("%d end produce product ...\n", num); pthread_cond_signal(&g_cond); printf("%d signal ...\n", num); pthread_mutex_unlock(&g_mutex); sleep(1); } return NULL;}int main(void){ int i; pthread_mutex_init(&g_mutex, NULL); pthread_cond_init(&g_cond, NULL); for (i = 0; i < CONSUMERS_COUNT; i++) pthread_create(&g_thread[i], NULL, consume, (void *)i); sleep(1); for (i = 0; i < PRODUCERS_COUNT; i++) pthread_create(&g_thread[CONSUMERS_COUNT + i], NULL, produce, (void *)i); for (i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++) pthread_join(g_thread[i], NULL); pthread_mutex_destroy(&g_mutex); pthread_cond_destroy(&g_cond); return 0;}
最后,下图为代码执行结果。
- 用条件变量来解决生产者消费者问题
- 线程同步2 ------ 用条件变量来解决生产者消费者问题
- 互斥锁加条件变量解决生产者消费者问题
- 用条件变量和信号量解决生产者和消费者问题
- 条件变量+互斥锁解决生产者消费者模型
- 消费者生产者问题---线程互斥锁+条件变量
- 互斥锁、条件变量:生产者消费者问题
- 生产者消费者问题条件变量实现
- Java多线程之生产者消费者问题<二>:使用重入锁、条件变量优雅地解决生产者消费者问题
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题
- OS: 生产者消费者问题(多线程+互斥量+条件变量)
- pthread-生产者消费者问题【采用互斥量和条件变量】
- OS: 生产者消费者问题(多线程+互斥量+条件变量)
- posix 条件变量与互斥锁 示例生产者--消费者问题 .
- 【IPC】互斥锁与条件变量及生产者-消费者问题
- 用Condition条件变量实现生产者消费者模式
- IOS 30多个iOS常用动画,带详细注释
- POJ3349---Snowflake Snow Snowflakes
- Linux学习笔记:常用命令总结
- nginx rewrite小问题
- 通过顶点颜色,制作高级贴图混合效果····
- 用条件变量来解决生产者消费者问题
- Maven Web项目构建
- Leetcode: Search a 2D Matrix II
- HDU 1863 畅通工程
- uva 674 Coin Change(类似完全背包)
- POJ_2942_Knights of the Round Table(点的双连通分量+二分图判定)
- ViewPager
- 我的前端学习笔记 box-sizing,calc,回调函数
- c 语言将字符串中连续多个空格用一个代替 并赋值到新的字符串