第八章 设计并发代码

​ 并发代码的设计要义再与谨慎思考,然而,多线程代码比串行代码需要考虑更多因素,不仅需要考虑普通因素,如:封装,耦合等,还需要分析共享那些数据,如何同步那些数据的访问等。本章内容包含:考虑使用多少线程,由那个线程执行什么代码,以及如何影响代码的清晰度,最后怎样让代码达到最优性能。

1.1在线程间切分任务方法

  1. 先在线程间切分数据,再开始处理

    eg:最简单的切分数据方法,将最前面的N个元素,分配给一个线程,将其后的N个元素分配给另外一个线程,以此类推。

  2. 以递归方式划分数据

    基本步骤:选定一个元素为比较的基准元素,将数据集按大小划分前后两部分。重新构成新序列,再针对这两部分递归排序。

  3. 依据工作类别划分任务

    要点:每个线程都独立执行不同的任务,不依赖其他线程,即每部分代码只承担单一的功能职责。

    方法如下:

  • 依据类别划分任务以分离关注点

  • 多线程正好“拔刀相助”

  • 借多线程分离关注点需防范两大风险

  • 在线程间按流程划分任务

  • 2.影响并发代码性能的因素

多线程代码的性能受到诸多因素的影响,具体如下:

  1. 处理器的数量

  2. 数据竞争和缓存乒乓

    一个数据复制到两个处理器对应的缓存中,从而让它们运行无碍,但如果其中一个线程改动了数据,则该变化必须传达至另一个处理器缓存,但是因为耗时,会导致数据竞争。

  3. 不经意共享

    若一个缓存块中数据互不关联,且需要被多个线程访问,这就会导致不经意共享问题。

  4. 数据的紧凑程度

    若单个线程访问的数据在内存松散分布,那它们就可能被纳入不同的缓存块,相反,假如单个线程访问的数据在内存中紧凑聚集,则它们很可能位于同一缓存块。

  5. 过度任务切换与线程过饱和

    如果线程数目过多,须全速运行的线程数目也持续增加,早晚将超出可供调配的处理器数目,操作系统也会随之开始剧烈的切换任务。

3设计数据结构以提升多线程程序的性能

  1. 针对复杂操作的数据划分

    首先遵循上述介绍的原则,只有是在线程间划分大块数据,它们全部都适用;其次,还要仔细分析数据访问模式的所有细节,并预判出所有损失的潜在诱因。

  2. 其他数据结构的访问模式

    给定一个线程,尽可能缩减它需要的数据量,令不同的线程所访问的数据互相充分隔离,以防不经意共享

4.设计并发代码时要额外考虑的因素

  1. 并发算法代码中的异常安全

    解决办法:加入异常安全,工具:std::async()

  2. 可伸缩性和Amdahl定律

    伸缩性的意义在于,如果系统增加了处理器,就应该确保应用程序能充分利用它们;Amdahl定律:若想利用并发特性提升程序性能,就应当统筹协调应用程序的整体设计,尽可能令并发程度达到最大,并且确保实际的工作量始终维持一定水平,足以让多个处理器有效运行。

  3. 利用多线程“掩藏”等待行为

    若线程所含处理器的数目等于线程的数目,则无论出于什么缘由而等待,一旦线程发生阻塞,处理器便无所事事,即浪费了CPU时间,因此,如果能够预知,某一线程将花费相当部分的运行时间进行等待。就可以多运行一个或几个线程,以充分利用空闲的CPU时间。

  4. 借并发特性改进响应能力

    可以指派一个新线程完整地执行冗长的任务,GUI事件则由另外一个线程专门处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力生活的海绵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值