条件变量:
  当一个线程互斥的访问某个变量时,它可能发现其他线程改变状态之前,它什么都做不了
例如:一个线程访问队列时,发现队列为空,它只能等待,直到其他线程将一个节点添加到队列中,这种情况就需要使用条件变量。

线程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条件变量的更多相关文章

  1. Linux多线程实践(8) --Posix条件变量解决生产者消费者问题

    Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_co ...

  2. posix 条件变量与互斥锁 示例生产者--消费者问题

    一.posix 条件变量 一种线程间同步的情形:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,而线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行. 在pthr ...

  3. Linux多线程实践(六)使用Posix条件变量解决生产者消费者问题

    前面的一片文章我们已经讲过使用信号量解决生产者消费者问题.那么什么情况下我们须要引入条件变量呢? 这里借用  http://www.cnblogs.com/ngnetboy/p/3521547.htm ...

  4. linux网络编程之posix条件变量

    今天来学习posix的最后一个相关知识----条件变量,言归正传. 下面用一个图来进一步描述条件变量的作用: 为什么呢? 这实际上可以解决生产者与消费者问题,而且对于缓冲区是无界的是一种比较理解的解决 ...

  5. 第四十章 POSIX条件变量

    条件变量 当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了 例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中.这种情况就需要用到条件 ...

  6. linux网络编程-posix条件变量(40)

    举一个列子来说明条件变量: 假设有两个线程同时访问全局变量n,初始化值是0, 一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待. 另外一个线程也 ...

  7. Linux互斥锁、条件变量和信号量

    Linux互斥锁.条件变量和信号量  来自http://kongweile.iteye.com/blog/1155490 http://www.cnblogs.com/qingxia/archive/ ...

  8. 并发编程(一): POSIX 使用互斥量和条件变量实现生产者/消费者问题

    boost的mutex,condition_variable非常好用.但是在Linux上,boost实际上做的是对pthread_mutex_t和pthread_cond_t的一系列的封装.因此通过对 ...

  9. 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

随机推荐

  1. iproute2工具

    iproute2工具介绍 iproute2是linux下管理控制TCP/IP网络和流量控制的新一代工具包,出现目的是替代老工具链net-tools.net-tools是通过procfs(/proc)和 ...

  2. 【C语言C++编程入门】——编译机制和语言标准!

    编程机制 编写程序时必须遵循确切步骤主要是取决于你的计算机环境.因为 C语言是可以移植的,所以它在许多环境中可用,其中包括 UNIX,Linux,Windows等等 . 不过,让我们首先来看一看许多环 ...

  3. CSP-S2020AFO记

    2020-10.11 考初赛辣. 选择题考了一堆时间复杂度,一个不会(卒) 我寻思这01背包哪里能用贪心? 啊,这,这,这手写快排竟如此简单,手写取Max,手写队列,两个字符串颠来倒去,竟活到爆! 震 ...

  4. SQL Server Management Studio (SSMS)单独安装,仅安装连接工具

    简单来说,SSMS是用于远程连接数据库与执行管理任务的一个工具.当安装SQL SERVER时,会默认安装.但也可以单独安装在不是数据库服务器的主机上. SQL Server Management St ...

  5. centos8平台使用pidstat监控cpu/内存/io

    一,安装pidstat: 1,安装 [root@localhost yum.repos.d]# yum install sysstat 2,查看版本: [root@localhost ~]# pids ...

  6. hystrix线程池隔离的原理与验证

    引子 幸福很简单: 今天项目半年规划被通过,终于可以早点下班.先坐公交,全程开着灯,买了了几天的书竟然有时间看了.半小时后,公交到站,换乘大巴车.车还等着上人的功夫,有昏暗的灯光,可以继续看会儿书.过 ...

  7. Hive Sql的日常使用笔记

    date: 2019-03-22 17:02:37 updated: 2020-04-08 16:00:00 Hive Sql的日常使用笔记 1. distinct 和 group by distin ...

  8. D. Rescue Nibel! 解析(思維、組合、離散化、差分)

    Codeforce 1420 D. Rescue Nibel! 解析(思維.組合.離散化.差分) 今天我們來看看CF1420D 題目連結 題目 給你\(n\)個區間,求有幾種方法使得\(k\)個區間的 ...

  9. java关键字之abstract

    Java 允许类,借口或成员方法具有抽象属性. abstract  修饰的类叫做抽象类,该类不能被实例化. abstract  修饰的方法叫抽象方法,抽象方法只有声明部分,没有具体的方法体. 接口总是 ...

  10. Redis常用命令(5)——Set

    SADD 格式:SADD key member [member ...] 作用:在集合key中插入一个或多个元素.如果member已经存在,则忽略member.如果key不存在则先创建集合key. 返 ...