关于Condition Variable的一些思考
可能大家都使用过condition variable(之后称cv),一些博客也对cv做了介绍,但是有的说的不完全正确,甚至有误导使用者的倾向,其实最合理的使用方式是查阅文档,
如果你英语还ok的话,http://en.cppreference.com/w/cpp/thread/condition_variable 读一遍即可 完全没有必要看我写的这些砖块,但是我的blog可能思路上更贴近初学者,可以借鉴一下。
背景不过多做介绍,使用condition variable的时候都要配合mutex使用,那么mutex就是为了什么呢,为什么要用这个东西呢?
为什么要这样设计?mutex多余吗?他是用来保护什么数据呢?
ok!让我们来从零开始。
condition variable的初衷是为了wait某一个东东变成true或false,然后此线程继续进行。
按照此需求,大概的代码应该是这样:
//version 1.0
Thread 1:
cv.wait();
Thread 2:
cv.signal();
这样的话有一个很严重的问题,如果t2先执行,那么t1岂不是永远停在那里了!这样与我们最初的构想完全不符!
于是产生了下面的写法:
//version 2.0
bool signaled = false;
thread 1:
if(!signaled)
cv.wait();
thread 2:
cv.signal();
signaled = true;
看上去不错吧!但是犯了一个很白痴的错误,bool并不是thread safe的,所以
//version 2.1
bool signaled = false;
thread 1:
lock;
if(!signaled) //1
unlock;
cv.wait(); //2
thread 2:
cv.signal(); //3
lock;
signaled = true; //4
unlock;
这样我们把signaled保护起来,保证thread safe了,会有什么问题吗?
当然有问题!如果执行顺序是这样的话,3-1-4-2 那么thread 1永远wait在那里了!
欸!为什么会这样呢!让我们从长计议!一开始为了保证signal是否发出,我们增加了一个标志位来判断是否信号已经发出,如果已经发出,那么cv不需要等待。接着,我们对thread safe进行了保证,然后现在又出现了执行顺序的问题!
仔 细思考一下,就会发现,其实导致问题的原因就在于需求的原子性并没有很好的用c++表达出来,你想想,thread 1的意思翻译成汉语就是“如果没有信号没有触发,那么我就等”,thread 2的意思很明显就是“触发!”,但是触发一句话到了c++语义中就变成了两个语句,多个指令,那么你很难满足我的需求,至少在不进行原子性语句约束的情况 下你无法满足我的需求。
所以 thread 1 这段代码就是一团糟!当进行wait操作之前,你能确定signaled为false吗?答案是否定的。
或者说thread 2 这段代码 当你signal之后,你的signaled马上变成true了吗? 答案也是否定的,你如果无法保证这两个语句的原子性,那么就无法达到需求。
所以我们继续修改:
//version 3.0
bool signaled = false;
thread 1:
lock;
if(!signaled) //1
cv.wait(); //2
unlock;
thread 2:
lock;
cv.signal(); //3
signaled = true; //4
unlock;
这样就ok了!但是如果你听说过spurious wakeup(可以自行查阅一下),那么3.0依然是不够完善的,
最终的版本是:
//version 4.0
bool signaled = false;
thread 1:
lock;
while(!signaled) //1
cv.wait(); //2
unlock;
thread 2:
lock;
cv.signal(); //3
signaled = true; //4
unlock;
然后我们回到最初的问题上去,为什么需要传入一个参数mutex,答案就很显然了,是为了让cv进行unlock操作的,当cv拿回线程的权杖的时候,再把mutex lock上,保证对称性。
关于Condition Variable的一些思考的更多相关文章
- C++关于Condition Variable
#include <condition_variable> #include <mutex> #include <future> #include <iost ...
- 关于condition variable的理解
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...
- c++并发编程之条件变量(Condition Variable)
条件变量(Condition Variable)的一般用法是:线程 A 等待某个条件并挂起,直到线程 B 设置了这个条件,并通知条件变量,然后线程 A 被唤醒.经典的「生产者-消费者」问题就可以用条件 ...
- C++11中的mutex, lock,condition variable实现分析
本文分析的是llvm libc++的实现:http://libcxx.llvm.org/ C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装.不 ...
- Condition Variable使用及其Thread Cancellation线程取消
条件变量Condition Variable的一般用法: 唤醒用法: struct { pthread_mutex_t mutex; pthread_cond_t cond; //whatever v ...
- 第8章 用户模式下的线程同步(4)_条件变量(Condition Variable)
8.6 条件变量(Condition Variables)——可利用临界区或SRWLock锁来实现 8.6.1 条件变量的使用 (1)条件变量机制就是为了简化 “生产者-消费者”问题而设计的一种线程同 ...
- [转] 条件变量(Condition Variable)详解
http://www.wuzesheng.com/?p=1668 条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A ...
- 条件变量(Condition Variable)详解
条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A中包含两个线程t1和t2.t1需要在bool变量test_cond ...
- 使用Condition Variables 实现一个线程安全队列
使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...
随机推荐
- ADO.NET改进版
ADO.NET从概念上来说是指定义一种与数据源进行交互的面向对象类库.类库即类的集合,也就是说ADO.NET主要是提供一了一些实现与数据源进行交互的一些类和接口. 其实就我个人看来,我觉得ADO.NE ...
- 自己动手写CPU之第五阶段(1)——流水线数据相关问题
将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第15篇,我尽量每周四篇 上一章建立了原始的OpenMIPS五级流水线结构,可是仅仅实现了一条ori指令,从本章開始,将逐步完 ...
- XML是什么,它能够做什么?——写给XML入门者
XML就可以扩展标记语言(eXtensible Markup Language).标记是指计算机所能理解的信息符号,通过此种标记,计算机之间能够处理包括各种信息的文章等.怎样定义这些标记,既能够选择国 ...
- 【转】zookeeper 的监控工具
公司很多产品会使用zookeeper,比如Meta消息中间件,在测试的过程中,我们经常需要查询zookeeper里面的信息来精确定位问题.目前项目中有开发团队自己写的浏览器node-z ...
- JavaScript中模块“写法”
在JavaScript模块到底是什么 event = function() { // do more return { bind: function() {}, unbind: function() ...
- .net控件dropdownlist动态绑定数据 ----转
DropDownList控件的使用(数据绑定)(.net学习笔记二) 一.在页面初始化时候将集合绑定到DropDownListpublic void Page_Load(Object src.Even ...
- ADO.Net连接模式
1.SqlConnection类 (1).通过构造函数创建一个SqlConnection对象,可以同时指定连接字符串 (2).通过SqlConnection对象的Open()方法打开数据库连接 (3) ...
- 在CSDN上看到的一个过滤方法,感觉还不错
/// <summary> /// 把字符串中包含的敏感词替换成别的关键字 /// </summary> /// <param name="s"> ...
- jquery实现带左右箭头和数字焦点的图片轮播手写代码
以前图片轮播经常用网上的插件,然后想说自己也要认真看看,一步一步弄明白,所以就自己研究写了个图片轮播的代码,我自己觉得还算是挺简单的.如有改进的地方,欢迎你能帮我指出,共同进步. (ps:博客园如何上 ...
- Picasso 加载图片到RelativeLayout之解决方案
Picasso 加载图片到ImageView 或者自己的自定义View都是可以直接调用对应API的,但是用into(0直接也加载到RelatieLayout就不好使了,可以这样来: Picasso.w ...