POSIX条件变量(生产者,消费者)
来源:互联网 发布:lemon oa mysql 编辑:程序博客网 时间:2024/05/01 16:22
POSIX条件变量
1,当一个线程互斥的访问条件变量的时候,它发现这个变量当前的状态不满足这个线程得以继续执行的要求
就需要等待其它线程对该变量进行更改,直到满足它的要求,不然的话,它什嘛也不做。。。。。。。。。
等待条件的满足。这个时候呢,,,就需要用到条件变量
如上,一个全局变量n = 0;
两个线程,都有加锁机制,一旦进入临界区,当线程1进入临界区之后,那么就会加锁,线程2也就进不去了
,然后根本无法使得n大于0,所以线程1也就无法往下继续执行了,出现了死锁
这个时候,我们就需要其它的手段来解决这个问题了,,,那么就是采用条件变量
通常一个进程进入临界区会加一个互斥锁(mutex,lock),那么条件变量需要跟互斥锁配合使用
为什么要配合使用呢???
1,我们所等待的条件n是多个线程都可以访问的。。。因而对这个条件的保护需要用到锁操作
2,一旦一个线程对条件进行了互斥锁加锁,那么其它的线程就无法进入到临界区了
所以说:条件变量能够跟一个锁配合在一起使用,那么条件变量在等待条件的时候,必须能够对这把锁进行
解锁,,,(也就是说:条件变量在等待的时候,第一步一定是先解锁,如果没有进行解锁,其
它线程没有机会进入到临界区中,还是跟上面死锁是一样的,一旦解锁了,其它线程就有可能
进入到临界区使得条件合适(n大于0)),同时一旦等待的线程对互斥锁进行了解锁,也允许
其它的线程进入到临界区,等待同样的一个条件
所以说:条件变量是一种新的同步对象,,,当进入到等待条件的时候,首先要进行解锁操作。。。
这也就是我们为什么需要条件变量的原因,,,
那么条件变量也可以用于生产者,消费者问题。。。。
例如:一个线程访问一个队列的时候,发现队列是空的时候,那么它就只能等待,,,直到其它线程将一个
节点放入到队列中的时候,可以向等待当中的线程发起一个通知。
这个时候,就用到了条件变量了
所以说:通过条件变量也能解决生产者,消费者问题,,,而且对于解决缓冲区是无界的。是比较理想的一种
解决方案(也就是说:生产者这边不管缓冲区是不是满,因为它认为缓冲区是无界的,这个时候,
我们只需要用一个互斥量和条件变量即可)
pthread_cond_init //初始化一个条件变量 pthread_cond_destroy//销毁一个条件变量 pthread_cond_wait //在一个条件上等待 pthread_cond_signal //当条件满足的时候,我们可以向一个等待的线程发起一个通知 pthread_cond_broadcast//向等待的所有线程发起通知
条件变量的使用规范
等待条件代码:
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);
使用条件变量来解决生产者消费者的问题
我们来看看下面这个程序:
#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 5#define PRODUCERS_COUNT 5//两个生产者一个消费者pthread_mutex_t g_mutex;//我们需要一个条件变量对象pthread_cond_t g_cond;//另外我们还要注意到建立线程(消费者+生产者的个数)pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT];int nready = 0; //当前缓冲区中的货物个数//为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 condition...\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(5);}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;}
运行结果:
我们再来看看细节问题:
生产者消费者的核心代码:
生产者:
while(1){pthread_mutex_lock(&g_mutex);++nready; pthread_cond_signal(&g_cond); pthread_mutex_unlock(&g_mutex); sleep(1); }
消费者:
while(1){pthread_mutex_lock(&g_mutex);while(nready == 0){pthread_cond_wait(&g_cond, &g_mutex);}--nready;pthread_mutex_unlock(&g_mutex); slee(1); }
1, 首先我们来看看:
pthread_cond_wait(&g_cond, &g_mutex);这个函数内部做了什嘛事情,,,
1,对g_mutex进行解锁(给其它线程进入临界区的条件,才能够更改条件)
其它线程也就有机会进入临界区,处于等待状态
而且,我们在使用这个函数之前,一定要先进行加锁操作。。。。
2,等待条件,直到有线程向它发起通知,才返回
3,当函数返回的时候,一定要对这个g_mutex进行加锁操作。。。。
上面这三者,构成了一个原语
2,再来看看这个函数:
pthread_cond_signal(&g_cond);向第一个等待条件的线程发起一个通知,如果没有任何一个线程处于等待条件的状态,这个通知将被忽略
3,这个函数
pthread_cond_broadcast
向所有等待的线程发起通知。。。。。
4,接下来,我们来讨论讨论为什么消费者这里要用while,if不行吗???
while(nready == 0){pthread_cond_wait(&g_cond, &g_mutex);}
1,当信号处理程序完毕的时候,,,等待的函数会重新等待一样,,就好像这个信号没有发生过一样,
这个函数会自动重启
2,虚假的唤醒,说明我们并没有等待到条件,,,,此时的nready还可能为0,用if达不到要求
- POSIX条件变量(生产者,消费者)
- posix 条件变量与互斥锁 示例生产者--消费者问题 .
- 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题
- Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题
- linux网络编程之posix 线程(四):posix 条件变量与互斥锁 示例生产者--消费者问题
- linux网络编程之posix 线程(四):posix 条件变量与互斥锁 示例生产者--消费者问题
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
- python 条件变量 生产者与消费者
- 消费者生产者问题---线程互斥锁+条件变量
- 线程 ,生产者. 消费者 互斥锁,条件变量
- 条件变量+互斥锁解决生产者消费者模型
- 互斥锁、条件变量:生产者消费者问题
- 使用条件变量实现生产者消费者模式
- 互斥锁加条件变量解决生产者消费者问题
- 生产者消费者问题条件变量实现
- posix 信号量---生产者消费者(一)
- posix 信号量---生产者消费者(二)
- java编程300例:6.将程序运行相关信息记录到日志中
- hdu 2089 不要62【DP】
- 多校3 5761 Rower Bo
- 邻接矩阵图的应用c++
- Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)
- POSIX条件变量(生产者,消费者)
- 数据结构实验之栈二:一般算术表达式转换成后缀式
- 安装驱动程序(3)--调整过滤驱动位置
- 利用栈实现二叉树的中序遍历(2)
- leetcode twosum
- Java Web 初级程序员 :第4天学习内容:String字符串
- SOA (面向服务的体系结构)
- Windows系统安全检查脚本
- Encountered a duplicated sql alias during auto-discovery of a native-sql query种种报错