Chapter 4:同步

本章主要介绍《C++并发编程实战》的第四章内容。

condition variables && future

很重要的一点,多线程开发使用的库函数,比如stl,boost,qt,哪些是线程安全或者可重入的吗?如果不明确就使用,问题就大了⊙▽⊙

扩展阅读:
并发编程系列之一:锁的意义


使用condition variables来等待事件,使用future来等待一次性事件

使用Condition variables来等待由另一个线程触发事件。C++提供了std::condition_variablestd::condition_variable_any,二者结合互斥元可以提供恰当的同步。前者只能和mutex一起工作,而后者_any可以与符合成为类似互斥元的最低标准的任何东西一起工作。
如下面的例子,通过condition_variable的语义,可以执行等待,除非满足条件否则线程阻塞。(在这里如果不使用条件等待,那么可以采用:循环地check是否满足条件;或者sleep一段时间再check,不满足再睡。但,这两种方式都会占用比较多的运行时间!所以不如使用condition.notify来得便利)
同时,这个例子也是很简洁的使用队列共享传输数据的场景之一,可以学习如何应用。

生产者
消费者

Building a thread-safe queue with condition variables

要构造一个线程安全的queue,那么一定需要保护共享变量的线程安全性。通过加锁可以达到这个要求,在这里还运用到了条件变量,每push一个元素,就会发出一个notify。而对于wait_and_pop()它在执行时候会在cond.wait(guard, [this]{ return !data.empty();})处阻塞,如果条件不满足则释放锁并继续等待,等待cond.notify_one()来唤醒。

Part1

Part2
Part3
prepare data
process data
调用Thread_safe_Queue

一次性事件之future

future的语义是一次性事件,一旦事件发生,future变成就绪态ready,然后无法复位。future是可移动的,而shared_future是可拷贝的,这表明一次只有一个实例指向特定的future状态。因此如果从多个线程访问单个future对象而不进行额外的同步,会出现data race和未定义行为。
同时也存在基于时间限制的等待,不过要注意,在计算机中存在多种时间,有的时间种类是非匀速的,在使用时候需要辨别。
可以使用std::async、packaged_task<>、或者promise<T>与future相结合来构建异步事件。
使用async可以启动一个异步任务,它返回一个future对象,当你需要任务的返回值的时候只要调用future的get(),线程会阻塞直到future就绪,然后返回该值,如下代码:


async

同步的其他方式

除去使用条件、事件,还可以使用其他方式来进行同步。这里涉及到不同的多线程并发模型,在翻阅了《七周七并发模型》后才理解4.4后续章节所描述的函数式编程(Functional Programming)、通信式编程(Communicating Sequential Process类似状态转换机或称actor model角色模型)其实是实现并发的不同方式。
函数式编程指的是函数调用的结果仅单纯依赖该函数的参数而不依赖任何外部状态,纯函数不修改任何外部状态,函数的影响完全局限在返回值上。这样也就不存在修改共享数据。而类似Haskell这样的编程语言,其所有函数在默认情况下都是纯函数。对于C++来说,由于它是多范式语言,因此其实也可以通过一些手段达到FP风格的编写。
另外一种方式通信顺序处理的思想也很简单,没有数据共享,每个线程可以独立推理得到,只需要基于它对接收到的消息进行反应。这样其实就是抽象成为了一个状态机:当它收到消息,就会依据初始状态进行操作,并以某种方式更新其状态,并能向其他线程发送消息(在实际实现中可能消息队列是共享的,但线程间不存在共享数据)。不过,这非常考验设计人员在编码前对任务的正确划分,同时,在当前一些开发中其实也可以发现有的就是这样一种思路。
在演示Actor model时候,示例代码的函数指针用得有趣。

定义和其中一个功能函数

循环执行state函数

从这两方式都可以看出如何正确编写并发程序的思路,那就是:控制数据共享!

在线程间划分工作的技术

不同的任务划分方式对数据共享,编码逻辑清晰都有影响需要仔细考虑。

  • 从数据划分
    在开始前划分数据;
    递归地划分数据

  • 从任务划分
    按任务类型划分:分工,比如刷墙,水管,装电
    按任务序列划分:比如买菜,洗菜,做菜

疑问

1.在代码最后,有一个检查是否为最后一个数据,如果是则退出,这一个地方是否也可以使用触发的方式来替代?
线程被关闭,在运行时候是否有类似方案?因为在Qt里如果用了信号槽,强行关闭线程是可能会引发问题的。

通过后续的学习发现其实中断线程的一种方法就是通过条件变量测试,比如主线程Button触发终止线程,导致修改线程的共享变量,在线程执行过程中会多次check该变量是否表示退出,如果表示退出就break循环或其他方式终止后续操作。不过要注意保护共享变量,同时这里也可能涉及到编译器优化,比如while(bState),编译器可能会直接把bState的值存储到寄存器中,因此即使该值发生了变更,执行线程并不会识别到!于是就有人提出了使用violate来修饰变量使得强制编译器每次都强制从内存中读取该变量。但有文章C/C++ Volatile关键词深度剖析.何登成又说其实这并没有太多效果。
中断线程是一个充满了风险的操作,在Qt中通常quit、exit和terminate,其实quit和exit仅仅是退出线程的事件循环(event-loop),如果该线程没有事件循环,那么其实它什么都不做,所以调用了quit、exit其实很多情况,线程的流程还是会继续走下去。而只要调用terminate,线程会立马终止。但终止一个运行中的线程会导致资源未清理、事件未完成,严重的会导致程序Crush!中断需谨慎。

PS:最近翻了多本介绍多线程开发的书籍,从《Thinking in java》、《C++面向对象多线程编程》、《CLR Via C#》、《深入理解计算机系统》到《C++并发编程实战》发现基本知识其实都一致且不多,短小精炼,但要能真正在Coding时候使用多线程技术,并不是一件容易的事,事事可期,不可预料的感觉。

PS:乱入一个Jay的视频~~
周杰伦的逆袭

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,976评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,249评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,449评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,433评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,460评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,132评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,721评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,641评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,180评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,267评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,408评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,076评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,767评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,255评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,386评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,764评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,413评论 2 358

推荐阅读更多精彩内容