POSIX条件变量
条件变量:
当一个线程互斥的访问某个变量时,它可能发现其他线程改变状态之前,它什么都做不了
例如:一个线程访问队列时,发现队列为空,它只能等待,直到其他线程将一个节点添加到队列中,这种情况就需要使用条件变量。
线程A: 线程B:
改变n
int n=0 进入临界区
进入临界区
更改 n>0
等待 n>0(该线程进入临界区其他的线程无法运行) 通知等待线程
操作n 退出临界区
退出临界区
注意:当一个线程进入临界区,等待n>0,其余的线程无法获取互斥量(同一个互斥量)进入临界区修改n,那么线程A就会一直等待。
就会出现死锁,所以我们引入了条件变量。条件变量要跟互斥量配合使用,一是因为多个线程都可以访问条件n>0;而是因为一个线程
对互斥量加锁,其他线程就无法获得互斥量修改n.所以条件变量一开始先解锁,那么线程就可以获得互斥量,修改n.也可以等待条件。
条件变量使用规范
等待条件代码:
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);
通知条件成立
int pthread_cond_signal(pthread_cond_t *cond);
等待条件成立
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
while(1)
{
pthread_mutex_lock(&g_mutex);
//为何使用while而不是if
//被信号打断的话,一种pthread_cond_wait重启,就行没有发生一样,或者pthread_cond_wait可能被虚假唤醒,所以要用while再次判断条件。
while(nready==0)
{
pthread_cond_wait(&g_cond,&g_mutex);
}
--nready;
pthread_mutex_unlock(&g_mutex);
}
pthread_cond_wait(原语)内部进行的操作:
一、对g_mutex进行解锁(其他消费者线程可以进行等待,生产者线程也可以改变条件)
二、等待条件,直到其他线程向它发起通知
三、返回的时候对互斥量重新加锁
while(1)
{
pthread_mutex_lock(&g_mutex);
nready++;
if(nready>0)
pthread_cond_signal(&g_cond);//条件满足,发起通知
pthread_mutex_unlock(&g_mutex);
}
pthread_cond_signal
向第一个等待条件的线程发起通知,如果没有任何一个线程处于等待条件的状态,这个通知将被忽略
pthread_cond_broadcast
向所有的等待线程发起通知
用条件变量解决生产者、消费者问题(缓冲区无界,假定仓库无限大)
1 #include<unistd.h>
2 #include<sys/types.h>
3 #include<fcntl.h>
4 #include<sys/stat.h>
5 #include<stdlib.h>
6 #include<stdio.h>
7 #include<errno.h>
8 #include <semaphore.h>
9 #include<pthread.h>
10 #define ERR_EXIT(m)\
11 do\
12 {\
13 perror(m);\
14 exit(EXIT_FAILURE);\
15 }while(0)
16 #define CONSUMERS_COUNT 2
17 #define PRODUCERS_COUNT 4
18
19 unsigned short in=0;
20 unsigned short out=0;
21 unsigned short produce_id=0;//当前正在消费的产品ID
22 unsigned short consume_id=0;//当前正在消费的产品ID
23
24 pthread_cond_t g_cond;
25 pthread_mutex_t g_mutex;
26 pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT ];
27
28 //消费者线程
29 int nready=0;//缓冲区没有产品
30 void* consume(void*arg)
31 {
32 int num=(int)arg;//线程编号
33
34 while(1)
35 {
36 pthread_mutex_lock(&g_mutex);
37 //当条件不成立,就一直等待。
38 while(nready==0)
39 {
40 printf("%d begin wait a condition...\n",num);
41 //跟互斥锁配合使用,先解锁,以便其他线程进入临界区修改条件,防止死锁。
42 pthread_cond_wait(&g_cond,&g_mutex);//在nready==0上等待。
43 //再加锁
44 }
45 //条件改变了
46 printf("%d end wait a condition...\n",num);
47 printf("%d begin consume product...\n",num);
48 --nready;//消费产品
49 pthread_mutex_unlock(&g_mutex);
50 sleep(1);
51 }
52 return NULL;
53 }
54 //生产者线程
55 void* produce(void*arg)
56 {
57 int num=(int)arg;
58
59 while(1)
60 {
61 pthread_mutex_lock(&g_mutex);
62 printf("%d begin produce product...\n",num);
63 nready++;//直接开始生产产品。
64 printf("%d end produce product...\n",num);
65 //条件成立,通知等待线程
66 pthread_cond_signal(&g_cond);
67 printf("%d signal \n",num);//某个线程发起通知
68 pthread_mutex_unlock(&g_mutex);
69 sleep(1);
70 }
71 return NULL;
72 }
73 int main(void)
74 {
75 int i;
76 //初始化互斥量和条件变量
77 pthread_mutex_init(&g_mutex,NULL);
78 pthread_cond_init(&g_cond,NULL);
79 //创建消费者线程
80 for(i=0;i<CONSUMERS_COUNT;i++)
81 {
82 pthread_create(&g_thread[i],NULL,consume,(void*)i);//产生了段错误.我们传递的是值,所以int num=(int)arg 而不是int num=*(int*)arg
83 }
84
85 sleep(1);//以便消费者进入等待
86 //创建生产者线程
87 for(i=0;i<PRODUCERS_COUNT;i++)
88 {
89 pthread_create(&g_thread[i+CONSUMERS_COUNT],NULL,produce,(void*)i);
90 }
91 //等待线程退出
92 for(i=0;i<CONSUMERS_COUNT+PRODUCERS_COUNT;i++)
93 {
94 pthread_join(g_thread[i],NULL);
95 }
96
97 pthread_cond_destroy(&g_cond);
98 pthread_mutex_destroy(&g_mutex);
99 return 0;
100 }
POSIX条件变量的更多相关文章
- Linux多线程实践(8) --Posix条件变量解决生产者消费者问题
Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...
- posix 条件变量与互斥锁 示例生产者--消费者问题
一.posix 条件变量 一种线程间同步的情形:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行. 在pthr ...
- Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题
前面的一片文章我们已经讲过使用信号量解决生产者消费者问题.那么什么情况下我们须要引入条件变量呢? 这里借用 http://www.cnblogs.com/ngnetboy/p/3521547.htm ...
- linux网络编程之posix条件变量
今天来学习posix的最后一个相关知识----条件变量,言归正传. 下面用一个图来进一步描述条件变量的作用: 为什么呢? 这实际上可以解决生产者与消费者问题,而且对于缓冲区是无界的是一种比较理解的解决 ...
- 第四十章 POSIX条件变量
条件变量 当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了 例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中.这种情况就需要用到条件 ...
- linux网络编程-posix条件变量(40)
举一个列子来说明条件变量: 假设有两个线程同时访问全局变量n,初始化值是0, 一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待. 另外一个线程也 ...
- Linux互斥锁、条件变量和信号量
Linux互斥锁.条件变量和信号量 来自http://kongweile.iteye.com/blog/1155490 http://www.cnblogs.com/qingxia/archive/ ...
- 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题
boost的mutex,condition_variable非常好用.但是在Linux上,boost实际上做的是对pthread_mutex_t和pthread_cond_t的一系列的封装.因此通过对 ...
- 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)
注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...
随机推荐
- iproute2工具
iproute2工具介绍 iproute2是linux下管理控制TCP/IP网络和流量控制的新一代工具包,出现目的是替代老工具链net-tools.net-tools是通过procfs(/proc)和 ...
- 【C语言C++编程入门】——编译机制和语言标准!
编程机制 编写程序时必须遵循确切步骤主要是取决于你的计算机环境.因为 C语言是可以移植的,所以它在许多环境中可用,其中包括 UNIX,Linux,Windows等等 . 不过,让我们首先来看一看许多环 ...
- CSP-S2020AFO记
2020-10.11 考初赛辣. 选择题考了一堆时间复杂度,一个不会(卒) 我寻思这01背包哪里能用贪心? 啊,这,这,这手写快排竟如此简单,手写取Max,手写队列,两个字符串颠来倒去,竟活到爆! 震 ...
- SQL Server Management Studio (SSMS)单独安装,仅安装连接工具
简单来说,SSMS是用于远程连接数据库与执行管理任务的一个工具.当安装SQL SERVER时,会默认安装.但也可以单独安装在不是数据库服务器的主机上. SQL Server Management St ...
- centos8平台使用pidstat监控cpu/内存/io
一,安装pidstat: 1,安装 [root@localhost yum.repos.d]# yum install sysstat 2,查看版本: [root@localhost ~]# pids ...
- hystrix线程池隔离的原理与验证
引子 幸福很简单: 今天项目半年规划被通过,终于可以早点下班.先坐公交,全程开着灯,买了了几天的书竟然有时间看了.半小时后,公交到站,换乘大巴车.车还等着上人的功夫,有昏暗的灯光,可以继续看会儿书.过 ...
- Hive Sql的日常使用笔记
date: 2019-03-22 17:02:37 updated: 2020-04-08 16:00:00 Hive Sql的日常使用笔记 1. distinct 和 group by distin ...
- D. Rescue Nibel! 解析(思維、組合、離散化、差分)
Codeforce 1420 D. Rescue Nibel! 解析(思維.組合.離散化.差分) 今天我們來看看CF1420D 題目連結 題目 給你\(n\)個區間,求有幾種方法使得\(k\)個區間的 ...
- java关键字之abstract
Java 允许类,借口或成员方法具有抽象属性. abstract 修饰的类叫做抽象类,该类不能被实例化. abstract 修饰的方法叫抽象方法,抽象方法只有声明部分,没有具体的方法体. 接口总是 ...
- Redis常用命令(5)——Set
SADD 格式:SADD key member [member ...] 作用:在集合key中插入一个或多个元素.如果member已经存在,则忽略member.如果key不存在则先创建集合key. 返 ...