当前位置: 首页 > news >正文

条件变量的接口函数和使用原则

条件变量的接口、常量、数据类型

1.静态创建一个条件变量(栈)

pthread_cond_t cond;

2.动态创建一个条件变量(堆)

pthread_cond_t * pCond = (pthread_cond_t *)malloc(sizeof(pthread_cond_t));

3.初始化静态条件变量(默认方式)

使用宏 PTHREAD_COND_INITIALIZER

4.动态初始化条件变量

int pthread_init(pthread_cond_t *cond, pthread_condattr_t *condattr);

5.销毁堆上创建的条件变量

int pthread_destroy(pthread_cond_t *cond);

6.使用条件变量进行等待

int pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t *mutex);

int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex_t *mutex,struct timespec * expiration);

7.唤醒条件变量

int pthread_cond_signal(pthread_cond_t * cond);

int pthread_cond_broadcast(pthread_cond_t * cond);

 

条件变量的使用原则

条件变量不允许复制,但是可以复制其指针。

线程从条件变量醒来时,一定要检查谓语是否成立。这是因为以下三个原因造成的:

1.唤醒可能被拦截:线程A被唤醒的过程中需要重新获取互斥量,如果互斥量被线程B首先获取到了,则线程B首先执行并重置了共享数据的状态,这时候切换回线程AA在没有检查谓语成立的情况下开始操作可能导致灾难性的后果,因为此时谓语已经不成立。

2.模糊谓语:在程序中使用模糊谓语可简化逻辑,而且并不会很影响性能。这种模糊谓语可能唤醒某个线程,该线程对应的精确谓语事实上是不满足的,所以需要重新检查谓语。

3.伪唤醒:这和实现相关了,保证条件变量的唤醒完全可预测可能降低系统的整体性能,线程可能在没有任何其他线程使用signal或者broadcast的前提下唤醒,不过这种概率很小,但并不是没有可能。

尽量不要再pthreads中使用UNIX信号。

发广播可看成是对发信号通用化,也可见发信号看成是发广播的优化版。不能使用发信号取代发广播。在使用发信号的地方使用发广播是完全可以的,当然前提是所有的唤醒线程都进行谓语测试。

对于一个队列模型,如果有一个生产者,多个消费者。如果生产者一次只放入一个产品,则可以使用发信号的方式。如果生产者一次放入多个产品则可以使用发广播的方式。

在发广播或者发信号的时候对于互斥量可以加锁也可以不加锁。不加锁的好处为潜在的高效率,如果唤醒线程加锁发信号,被唤醒的线程需要尝试着获取互斥量,这时获取失败,又切换回唤醒线程。这会导致两次无意义的切换,当然这个实现可以优化的。加锁的好处在于保证高优先级的线程首先执行,如果不加锁,则所有的线程(不只是将要被唤醒的线程还可能有其他的没有使用条件变量的线程)都有可能获取当前锁。如果低优先级的条件变量首先获得了锁,高优先级的线程将不能被保证。而使用加锁的方式发广播信号之后,解锁后,系统会优先调度优先级高的线程先获得锁,因此保证了公平性(这里的公平更接近于香港廉政署的定义:公平不是每个人都赚十块钱,公平是你有赚100元的能力,社会保证你能赚100元。你有能力赚10元时,社会保证你赚10 D)。



本文转自hipercomer 51CTO博客,原文链接:http://blog.51cto.com/hipercomer/914921

相关文章:

  • C# DataGridView中DataGridViewComboBoxCell列,下拉框事件的处理【完美解决】
  • C# 中的枚举类型 enum (属于值类型)
  • jQuery选择器之表单对象属性过滤选择器Demo
  • Cloudera Mountable HDFS (hadoop-fuse-dfs).
  • linux reiserfs文件系统损坏后的数据恢复过程记录
  • 把一个用户的相关权限赋予另外一个用户
  • gets函数的不安性详解
  • Silverlight知识链接整理(11月-12月)
  • ORACLE 分区与索引
  • C# 视频监控系列(2):客户端——封装API (1)
  • Silverlight书籍推荐阅读排行榜【续】
  • 文本编辑命令
  • VI批量替换
  • Heron and His Triangle 2017 沈阳区域赛
  • Oracle在线 redo log文件丢失后的恢复
  • 时间复杂度分析经典问题——最大子序列和
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • CentOS 7 修改主机名
  • classpath对获取配置文件的影响
  • django开发-定时任务的使用
  • Fundebug计费标准解释:事件数是如何定义的?
  • Javascript编码规范
  • Javascript弹出层-初探
  • jquery cookie
  • Linux各目录及每个目录的详细介绍
  • Node + FFmpeg 实现Canvas动画导出视频
  • passportjs 源码分析
  • Python爬虫--- 1.3 BS4库的解析器
  • Spark学习笔记之相关记录
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 构造函数(constructor)与原型链(prototype)关系
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 开源地图数据可视化库——mapnik
  • 面试总结JavaScript篇
  • 浅谈web中前端模板引擎的使用
  • 嵌入式文件系统
  • 区块链分支循环
  • 双管齐下,VMware的容器新战略
  • 用简单代码看卷积组块发展
  • 智能网联汽车信息安全
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • Linux权限管理(week1_day5)--技术流ken
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 数据库巡检项
  • 我们雇佣了一只大猴子...
  • #android不同版本废弃api,新api。
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (接口封装)
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (三)c52学习之旅-点亮LED灯
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)winform之ListView
  • (转载)虚函数剖析