可能大家都使用过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的一些思考的更多相关文章

  1. C++关于Condition Variable

    #include <condition_variable> #include <mutex> #include <future> #include <iost ...

  2. 关于condition variable的理解

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...

  3. c++并发编程之条件变量(Condition Variable)

    条件变量(Condition Variable)的一般用法是:线程 A 等待某个条件并挂起,直到线程 B 设置了这个条件,并通知条件变量,然后线程 A 被唤醒.经典的「生产者-消费者」问题就可以用条件 ...

  4. C++11中的mutex, lock,condition variable实现分析

    本文分析的是llvm libc++的实现:http://libcxx.llvm.org/ C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装.不 ...

  5. Condition Variable使用及其Thread Cancellation线程取消

    条件变量Condition Variable的一般用法: 唤醒用法: struct { pthread_mutex_t mutex; pthread_cond_t cond; //whatever v ...

  6. 第8章 用户模式下的线程同步(4)_条件变量(Condition Variable)

    8.6 条件变量(Condition Variables)——可利用临界区或SRWLock锁来实现 8.6.1 条件变量的使用 (1)条件变量机制就是为了简化 “生产者-消费者”问题而设计的一种线程同 ...

  7. [转] 条件变量(Condition Variable)详解

    http://www.wuzesheng.com/?p=1668 条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A ...

  8. 条件变量(Condition Variable)详解

    条件变量(Condtion Variable)是在多线程程序中用来实现“等待->唤醒”逻辑常用的方法.举个简单的例子,应用程序A中包含两个线程t1和t2.t1需要在bool变量test_cond ...

  9. 使用Condition Variables 实现一个线程安全队列

    使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...

随机推荐

  1. 通过YAJL获取json中的值

    这里主要是举例说明一下假设通过yajl获取json中的值. 对于array和object来说,获取的方式略有不同,详细能够參考以下的代码. 我仅仅是从网上搜集信息.知道有这么一种方法.假设还有别的方法 ...

  2. android xml布局文件属性说明

    android xml布局文件属性说明 [摘]android xml布局文件属性说明 LinearLayout和RelativeLayout 共有属性:java代码中通过btn1关联次控件androi ...

  3. java 命令行制定logback参数

    -Dlogback.configurationFile=file:///export/Workspace/apache-cassandra/apache-cassandra-main/target/b ...

  4. html加载js那些事

    浏览器通过内置的JavaScript引擎,读取网页中的代码,对其处理后运行. JavaScript代码嵌入网页的方法 在网页中嵌入JavaScript代码有多种方法. 直接添加代码块 通过script ...

  5. zoj1076 Gene Assembly

    这道和zoj1025一样,本质是贪心算法,首先要求任意最长的序列,我们只要保证最长就行,也就是在一幅图中找一个最长的链,首先我们需要根据y排序(输入为x,y),因为y大的肯定在y小的后面,然后就直接贪 ...

  6. sql server 2008 (1)(2)

    ---恢复内容开始--- sql server 2008 (1) 系统数据库 master tempdb module 正文 数据库管理员(DBA)的一项基本的技能是对SQL数据库引擎的系统数据库的深 ...

  7. React 从0开始 消息传递

    React笔记 React 数据决定DOM 以往的做法是通过JS去操作DOM 将数据填充 JSX Jsx javascript xml HTML的结构组装到js中 jsx使用style的时候 不能直接 ...

  8. Delphi 进阶基础技能说明

    以下讨论均基于Delphi XE8,主要是利用DELPHI新版的功能,如:Unicode,泛型,匿名函数等[XE2 后应该都支持]. 用新特性的好处是少写代码,提高效率.本博客不再讨论Delphi旧版 ...

  9. Android第三方应用分享图文到微信朋友圈 & 微信回调通知分享状态

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWQAAAKUCAIAAAC8A9XzAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWX ...

  10. HTML5 服务器发送事件(Server-Sent Events)介绍

    w3cschool菜鸟教程 Server-Sent 事件 - 单向消息传递 Server-Sent 事件指的是网页自动获取来自服务器的更新. 以前也可能做到这一点,前提是网页不得不询问是否有可用的更新 ...