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

线程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. beego log

    package main import ( "github.com/astaxie/beego/logs" _ "xcms/routers" _ "x ...

  2. 使用PyPdf2合并PDF文件(没有空白、报错)

    使用PyPdf2合并PDF文件(没有空白.报错) 对于合并之后pdf空白,或者出现 'latin-1' codec can't encode characters in position 8-11: ...

  3. Nacos配置中心使用

    在系统开发过程中,开发者通常会将一些需要变更的参数.变量等从代码中分离出来独立管理,以独立的配置文件的形式存在.目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进 ...

  4. Linux入门到放弃之一《在VMware虚拟机中安装Linux系统(RedHat)》

    1.启动VMware: 2.新建虚拟机: 3.自定义配置(1安装客户机操作系统点击"稍后安装操作系统"2选择客户机操作系统为Linux,版本为Red Hat Enterprise ...

  5. eclipse快捷键(Mac版)整理

    eclipse快捷键(Mac版)整理 前言: 最近在学习JDBC,老师用的是eclipse,对于习惯了IDEA的我来说,没有了快捷键,效率明显下降. 我认为,开发工具的熟练使用,也是程序员必备的一项技 ...

  6. Redis可以做哪些事?

    Redis是一种基于键值对的NoSQL数据库,它的值主要由string(字符串),hash(哈希),list(列表),set(集合),zset(有序集合)五种基本数据结构构成,除此之外还支持一些其他的 ...

  7. AtCoder Grand Contest 013D: Piling Up 题解

    题意简化: [luogu] Piling Up 一开始有n个颜色为黑白的球,但不知道黑白色分别有多少,m次操作,每次先拿出一个球,再放入黑白球各一个,再拿出一个球,最后拿出的球按顺序排列会形成一个颜色 ...

  8. Go语言的互斥锁Mutex

    目录 一.使用方法 二.死锁场景 1.Lock/Unlock不是成对出现 2.锁被拷贝使用 3.循环等待 一.使用方法 Mutext是互斥锁的意思,也叫排他锁,同一时刻一段代码只能被一个线程运行,两个 ...

  9. 深入理解golang:内存分配原理

    一.Linux系统内存 在说明golang内存分配之前,先了解下Linux系统内存相关的基础知识,有助于理解golang内存分配原理. 1.1 虚拟内存技术 在早期内存管理中,如果程序太大,超过了空闲 ...

  10. CSP-S 2020模拟训练题1-信友队T1 四平方和

    题意简述 \(n\)是正整数,其四个最小的因子分别为\(d_1,d_2,d_3,d_4\). 求对于所有的\(n \le m\)满足 \[d_1^2+d_2^2+d_3^2+d_4^2=n \] 的\ ...