条件变量

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

条件变量和互斥锁为什么要配合使用?

  1. 条件本身就是公共资源,多个线程同时方式时,必须使用互斥锁在临界区内对条件进行保护。
  2. 条件变量的作用是在等待某个条件达成时自身要进行睡眠或阻塞,避免忙等待带来的不必要消耗;当被唤醒时,会重新尝试加锁,如果锁成功,才进行之后的流程;否则解锁,继续阻塞

条件变量函数

pthread_cond_init

功能:
initialize condition variables
原型:
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
参数:
cond : 指向结构pthread_cond_t的指针
attr : 条件变量的属性结构的指针
返回值:
成功 : 0
失败 : 返回错误码

pthread_cond_destroy

功能:
destroy condition variables
原型:
int pthread_cond_destroy(pthread_cond_t *cond);
参数:
cond : 指向结构pthread_cond_t的指针
返回值:
成功 : 0
失败 : 返回错误码

pthread_cond_wait

功能:
wait on a condition
原型:
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
参数:
cond : 指向结构pthread_cond_t的指针
mutex : 互斥锁
返回值:
成功 : 0
失败 : 返回错误码

pthread_cond_signal

功能:
signal a condition
原型:
int pthread_cond_signal(pthread_cond_t *cond);
参数:
cond : 指向结构pthread_cond_t的指针
返回值:
成功 : 0
失败 : 返回错误码

pthread_cond_broadcast

功能:
signal a condition
原型:
broadcast a condition
参数:
cond : 指向结构pthread_cond_t的指针
返回值:
成功 : 0
失败 : 返回错误码

条件变量使用规范

等待条件代码

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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> #include <semaphore.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0) #define CONSUMERS_COUNT 2 //消费者线程的个数
#define PRODUCERS_COUNT 1 //生产者线程的个数 int nready = 0;
pthread_cond_t g_cond;
pthread_mutex_t g_mutex; pthread_t g_thread[CONSUMERS_COUNT + PRODUCERS_COUNT]; //总线程数 void *consume(void *arg)
{
int num = (int)arg;
while (1)
{
pthread_mutex_lock(&g_mutex);
while(nready == 0)
{
printf("%d wait a condition...\n", num);
pthread_cond_wait(&g_cond, &g_mutex);
}
printf("%d end wait...\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 singal ...\n",num);
pthread_mutex_unlock(&g_mutex);
sleep(1);
} return NULL;
} int main()
{
int i;
pthread_cond_init(&g_cond, NULL);
pthread_mutex_init(&g_mutex, 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_cond_destroy(&g_cond);
pthread_mutex_destroy(&g_mutex); return 0;
}

pthread_cond_wait

  1. 对mutex进行解锁
  2. 等待条件,直到有线程向它发起通知
  3. 重新对mutex进行加锁操作

pthread_cond_signal

向等待的条件的线程发起通知,如果没有任何一个处于等待条件的状态,这个通知将被忽略

为什么要用while

  1. pthread_cond_wait会自动重启,就像这个信号没有发生过一样
  2. pthread_cond_wait可能会被虚假的唤醒,当被虚假唤醒后,需要重新判断条件

第四十章 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. linux网络编程-posix条件变量(40)

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

  6. POSIX条件变量

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

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

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

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

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

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

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

随机推荐

  1. js模拟下拉菜单-键盘、鼠标(代码详解)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. spring源码分析系列4:ApplicationContext研究

    ApplicationContext接口 首先看一下一个最基本的上下文应该是什么样子 ApplicationContext接口的注释里写的很清楚: 一个基本applicationContext应该提供 ...

  3. web 前端优化-戈多编程

    大家好,我是戈多,从事web开发工作接近三年了,今天来归纳下web前端优化的解决方案(码农搬砖工,来自各网络汇总) 1.减少Http请求 http请求越多,那么消耗的时间越多,如果在加上网络很糟糕,那 ...

  4. cogs2550. 冰桥,升起来了!

    [问题背景] 11月16日: 今天要来到南极洲的一角来考察啦!南极的空气真的很好呢,只不过有点冷,雪什么的真是太可爱了!这次我要在一个冰谷(应该说是山谷的地方)考察,考察点在这山谷的两边(希望不要掉下 ...

  5. ios手机通过fiddler抓去Https协议包时证书问题

    解决Fiddler无法抓取ios端HTTPS请求的问题 南天E心 关注 2018.01.15 10:36 字数 281 阅读 909评论 0喜欢 0 近日公司服务升级,将所有的接口请求由HTTP升级为 ...

  6. Beautiful Soup 4.2.0 文档(一)

    Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时 ...

  7. CentOS 7.6 Telnet服务搭建(Openssh升级之战 第一任务备用运输线搭建)

    (以下内容亲手完成,如果需要搬走记得把写博的小白的名字和邮箱一起搬走) 出来玩(学习),总是要还的! 有不明的问题的时候,都来博客园转转,总能找到答案或者灵感,开博3个月都没发一篇帖(不晓得管理员有何 ...

  8. Ubuntu16.04 安装apache+mysql+php(LAMP)

    记录下ubuntu环境下安装apache+mysql+php(LAMP)环境. 0x01安装apache sudo apt-get update sudo apt-get install apache ...

  9. Circle Problem From 3Blue1Brown (分圆问题)

    Background\text{Background}Background Last night, lots of students from primary school came to our c ...

  10. ‎Cocos2d-x 学习笔记(15.3) EventDispatcher DirtyFlag 脏标记

    1. 定义 用枚举定义脏标记的4种类型. enum class DirtyFlag { NONE = , FIXED_PRIORITY = << , SCENE_GRAPH_PRIORIT ...