在上一篇文章《深入理解Linux 条件变量2:使用条件变量实现[生产-消费]框架》中,我们通过示例代码演示了条件变量的使用。从条件变量的API接口中我们很容易发现,条件变量必须配合着互斥锁使用,那么问题来了:
条件变量的设计,为什么要结合着互斥锁使用呢?

针对这个问题,网上有一种流行说法:

条件变量配合着互斥量使用,是为了解决 在线程A中调用了 pthread_cond_wait,但是线程A还没有进入wait cond的时候,线程B调用了pthread_cond_signal,如果不用mutex,这个cond_signal就丢失了,而如果加上了锁,则线程B必须要等到mutex被释放了的时候才能调用pthread_cond_signal。

这种说法貌似是挺有道理的,我们会想当然的以为条件变量就是个普通变量,或者说是个单独的,类似于int var这种的独立变量,信号发送,如果没有cond_wait,这个信号就丢失了。但事实是这样的吗?

实践是检验真理的唯一条件,在上一篇文章《深入理解Linux 条件变量2:使用条件变量实现[生产-消费]框架》 代码中,在main中,我们先创建了生产线程,然后等待了2s才创建消费线程,代码如下:

     pthread_create(&pid, NULL, th_producer, NULL);sleep(2);printf("start create consumer thread.\n");pthread_create(&cid, NULL, th_consumer, (void *)th_consum1);

而在生产线程中每隔100ms就向消息队列中添加一个节点消息,然后调用pthread_cond_signal 向条件变量发送信号,如果按照上面的说法,理论上在消费线程运行之前的pthread_cond_signal都会丢失,那么程序运行结果呢? 如下:

start create consumer thread.
------- [th_consum1] get 0 --------
------- [th_consum1] get 1 --------
------- [th_consum1] get 2 --------
------- [th_consum1] get 3 --------
------- [th_consum1] get 4 --------
------- [th_consum1] get 5 --------
------- [th_consum1] get 6 --------
------- [th_consum1] get 7 --------
------- [th_consum1] get 8 --------
------- [th_consum1] get 9 --------
------- [th_consum1] get 10 --------
------- [th_consum1] get 11 --------
------- [th_consum1] get 12 --------
------- [th_consum1] get 13 --------

很明显,在pthread_cond_wait之前 的signal 并没有丢失,这就证明上面的说法是不对的,条件变量并不是一个简单的变量,而是一个计数器,每phread_cond_signal一次,则对条件变量计数递增,对应的,每pthread_cond_wait一次,则对条件变量计数递减,这样设计,我个人觉得对于开发者来说是非常友好的,开发者在实现自己的程序逻辑时,会更加方便和简单。

那既然不是上面说的原因,条件变量配合着锁的原因到底是什么呢?

条件变量配合互斥锁使用的真实原因

在《Unix环境高级编程》中,其实有答案,只不过答案太过简练了,没有过多的解释。我就以个人的理解来解释一下:

  1. 条件变量用于标识工作队列的状态。仅仅代表工作队列中有没有工作节点、工作队列状态变化,没有其他额外的含义,这本来就是它的设计初衷,只不过类似于linux链表结构 struct slist_s 设计一样,跟业务解耦了,开发者爱怎么用就怎么用,条件变量就是代表开发者自己的工作队列状态。
  2. 既然条件变量是标识工作队列的状态,那么我们在工作队列中的操作中使用了条件变量,这个条件变量就变成了工作队列的一部分,而工作队列一定是个共享资源,所以对于工作队列的操作,最好是要配合着互斥锁使用的,因为这样安全、有序。

我觉得答案就是这么简单,起码这种解释能够帮助你我更好的理解和使用条件变量。

pthread_cond_wait 对 mutex的影响

在上一篇文章《深入理解Linux 条件变量2:使用条件变量实现[生产-消费]框架》 代码中,消费者线程里,调用pthread_cond_wait前面 对mutex 加锁了:

         pthread_mutex_lock(&mutex);while(slist_empty(&g_msg_head)){pthread_cond_wait(&cond_hasProduct, &mutex);}// 取消息队列的首个 节点消息slist_for_each_entry_safe(&g_msg_head, tmp, pos, msg_t, list){printf("------- [%s] get %d --------\n", name, pos->data);slist_del(&pos->list, &g_msg_head);free(pos);pos = NULL;break;}pthread_mutex_unlock(&mutex);

有些人可能会有疑问,pthread_cond_wait阻塞了线程,而前面已经调用了 pthread_mutex_lock,也就是对mutex加锁了,那别的线程是不是就再也拿不到mutex了?答案是:不会。
我们简单说一下调用pthread_cond_wait干了什么,简单的说做了下面2件事儿:

  1. 自动把调用线程放到等待条件的线程列表上。
  2. 对互斥量解锁。

注意: 上述2个动作,都是原子操作,所谓原子操作,就是这2个动作是连续的,并且不会被别的程序干扰,比如CPU调度,一定能保证这2个动作一气呵成。这就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作之间的时间通道。

当条件变量有变化时,pthread_cond_wait 会返回,简单的说又做了下面2件事儿:

  1. 条件变量状态变化时,内核收到pthread_cond_signal信号,会从 等待条件的线程列表里,按照内部调度算法,唤醒至少1个线程。
  2. 被唤醒的线程中,pthread_cond_wait返回,并且互斥量会再次被锁住。

从上面的分析,也可以看出,条件变量的设计,既然包括了互斥量,内部也帮助开发者实现了对互斥锁的自动解锁和自动上锁。

深入理解Linux 条件变量3:条件变量为什么要配合着锁使用?相关推荐

  1. 理解 Linux 条件变量

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/cheungmine/article/details/37317429 理解 Linux 条件变量 1 ...

  2. 深入理解Linux 条件变量2:使用条件变量实现[生产-消费]框架

    前言 在上一篇文章<深入理解Linux 条件变量1:使用场景.接口说明>我们简单介绍了条件变量的使用场景以及相关接口,正如大神linus所说:talk is cheap,show me t ...

  3. Linux——线程同步(条件变量、POSIX信号量)和线程池

    一.线程同步 (一).概念 线程同步是一种多线程关系,指的是线程之间按照特定顺序访问临界资源,进而能够避免线程饥饿问题. 所谓线程饥饿指的是某个线程长期"霸占"临界资源,导致其他线 ...

  4. Linux线程同步之条件变量

    与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享 ...

  5. linux线程同步(2)-条件变量

    一.概述                                                    上一篇,介绍了互斥量.条件变量与互斥量不同,互斥量是防止多线程同时访问共享的互斥变量来保 ...

  6. Linux 线程学习之条件变量

    互斥锁:用来上锁. 条件变量:用来等待,当条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 函数介绍: 1. 名称: pthread_cond_init 目标: 条 ...

  7. linux 条件变量函数,Linux线程同步之条件变量

    条件变量变量也是出自POSIX线程标准,另一种线程同步机制,.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量 ...

  8. 【Linux学习009】脚本编程之变量、条件测试和条件判断

    一.Bash环境变量 bash中变量有四种种类型:环境变量.本地变量(局部变量).位置变量.特殊变量. 1.环境变量 环境变量作用范围最广,所有子bash进程都能够访问环境变量中的值,定义环境变量的方 ...

  9. [转]Linux线程同步之条件变量

    与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和互斥锁同时使用. 条件变量使我们可以睡眠等待某种条件出现.条件变量是利用线程间共享 ...

最新文章

  1. 北大95后「AI萝莉」回来了,一次中8篇顶会论文的她,现在达摩院开源7大NLP模型...
  2. 2019年云计算发展状态
  3. C# 7.0中的解构功能---Deconstruct
  4. 高品质美食PSD分层海报,吸睛有食欲
  5. Oracle的latch机制源代码解析——借postgresql猜测Oracle的latch
  6. 不错的Unity教程
  7. 一个大一计算机学生的学期总结(2022下半年)
  8. matlab自由落体程序,基于MATLAB的自由落体运动仿真.pdf
  9. 无锡工艺技术计算机信息管理论文,无锡工艺职业技术学院05/06学年第一学期.doc...
  10. 3D建模:14个建模小技巧
  11. 2021年中国高空作业平台行业发展现状及竞争格局分析,国产品牌异军突起「图」
  12. 想学设计?这6款设计软件不能不知道
  13. html5 xml在线编辑,XML 编辑器
  14. 你离顶尖游戏大厂只差这份招面试攻略啦
  15. 冰岛的数据中心产业蓝图
  16. vue前端下载文件的2种方式
  17. 浅谈erlang游戏服务器项目--英雄远征服务启动流程
  18. English语法_并列连词-or
  19. Typora的使用【保姆级教学】
  20. kettle 生成随机数

热门文章

  1. python start方法_进程方法 run和start的区别
  2. Linux怎么同步另一台设备的时间
  3. 辅材先生之打开传统向互联网+辅材这把锁
  4. 介绍分享几款免费的在线Web文件管理器
  5. 算术右移和逻辑右移区别
  6. 想把手机内容投屏到电脑 并且可以用电脑控制手机怎么办,很简单
  7. html js 打印 图片不显示 canvas
  8. android 计步器 计算当前的行走步数
  9. vue集成Luckyexcel实现在线编辑Excel,可自行导入,也可从服务器端获取
  10. 【转】我和权威的故事