设计并发算法的方法论

一. 什么是并发?和并行的区别?

单个处理器上采用单核处理多个任务即为并发,在这种情况下,操作系统的调度程序会频繁且迅速地从一个任务切换到另一个任务,因此看起来所有任务是同时进行的;
而并行是在不同的计算机、处理器或处理器核心上同时运行多个任务

二. 为什么需要设计并发程序?

简单来说就是为了提高系统性能,提高系统资源(cpu)的利用率,将CPU的计算能力发挥到极致。

但是并发应用程序会出现很多问题,如下:

  1. 数据竞争:两个或多个任务同时对一个共享变量进行写入操作,那么该变量的最终结果取决于这些任务的执行顺序。
  2. 死锁: 例如当任务A需要等待任务B释放某个资源才能往下执行,而任务B又需要等待任务A释放某个资源才能往下执行,这样就形成了死锁。
    死锁形成的四个必要条件:
    (1)互斥条件:死锁中涉及的资源不是 同时共享的,任意时刻只能被一个任务占有;
    (2)不可抢占条件:对于某个任务已占有的资源不能被其他任务抢占;也就是说,该资源只能由占有它的任务自己释放;
    (3)占有并等待条件:当某个任务在请求获取其他资源时,不会释放掉已经占有的资源;
    (4)循环等待:例如任务1等待任务2占有的资源,任务2等待任务3占有的资源,而任务3等待任务1占有的资源。这样就形成了循环等待。
    处理死锁的方法:
    (1)忽略:即出现死锁则停止应用程序并且重新执行,由于简单,是常用的机制;
    (2)检测:检测到死锁,则结束某个任务并强制释放某一资源;
    (3)预防:预防发生死锁的四个必要条件中的一条或多条;
    (4)规避:在某一任务执行之前得到该任务需要的所有资源信息,这样就能判断该任务是否可以执行。
  3. 资源不足:某个任务无法获取维持其继续运行的资源,或者等待时间过长,这就需要考虑任务占有资源的时间因素,来实现一个算法确保公平性原则。
  4. 活锁:可能是同步机制设置的不好,例如:有两个任务,都需要用到资源1和资源2,假设任务1获得了资源1并对资源1加了锁,任务2获得了资源2并对资源2加了锁。当它们获取不到所需的资源时,就会释放已有的资源并且重新开始循环(破坏了死锁发生的四个条件之一)。这种情况可以无限地持续下去,所以这两个任务都不会结束自己的执行过程。
  5. 优先权反转:当一个低优先权的任务获得了高优先权需要的资源时,低优先权的任务则会在高优先权任务之前执行。
三. 处理并发程序中的问题:同步

同步是一种协调多个任务以获得预期结果的机制,主要有两种方式:

  1. 控制同步:当一个任务依赖于另一个任务结束时,第二个任务不能在第一个任务之前完成;
  2. 数据访问同步:两个或多个任务访问不能同时访问共享变量。即在任意时间里,只有一个任务可以访问该变量。
    同步算法会为并发程序带来额外的开销,这就涉及并发算法的粒度,如果算法有着粗粒度,则同步机制的开销就小,反之则大。

ps:任务的通信方式有两种:1.共享内存:通常用于在同一计算机上执行多任务的情况,当涉及到写入的程序段需要使用同步机制将其设置为临界段 2. 消息传递:通常用于在不同计算机上执行多任务的情况,如果发送方保持阻塞并等待响应,那么就是同步通信;如果发送方在发送消息后继续执行自己的流程,那么就是异步通信

四. 设计并发算法的方法论

该方法论基于Intel公司在其“Threading Methodologgy:Principles and Practices"文档中给出的方法论。
起点:算法的一个串行版本(很重要),体现在以下两方面:
(1)算法的串行版本可以用来测试并发算法是否产生了正确的结果(测试阶段)
(2)算法的串行版本可以用来与并发算法比较吞吐量,以此来观察并发处理是否能够改善响应时间提升算法一次性所能处理的数据量(调整阶段)

方法论有以下5个步骤:
(1)分析: 通过算法的串行版本来寻找代码中哪些部分可以以并行方式运行。通常关注的是那些执行过程花费时间较多或者执行代码较多的部分,实现这些部分的并发版本则能获得较大的性能改进。
在这个过程中使用循环排查的方法,让其中某些部分的代码独立于其他部分的代码

(2)设计:根据同步机制实现的两种方式可以有两种设计方式:
A. 任务分解:将代码划分成两个或多个可以立刻执行独立任务时,即任务分解。当其中某些任务可能必须按照某种给定的顺序来执行时,则必须使用控制同步的机制来实现。
B. 数据分解:当使用同一任务的多个实力分到对数据集的一个子集进行处理时,即数据分解。当这些任务需要修改数据时,则必须使用数据同步的机制。
关于对任务的分解,需要注意的是分解后的算法粒度大小,如果分割成很多小任务(粒度过小),则实现同步机制所需额外引入的代码就会导致性能下降。如果粒度较大,分割的任务数量少于核数,那么就没有充分利用全部的资源。

(3)实现:用java的线程库

(4)测试:根据算法的串行版本来验证并发版本算法得到的结果是否正确

(5)调整:对比并发算法和串行算法的吞吐量,如果性能没有提升,则重新审查该算法找出原因修改。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值