第一章-走入并行世界

1.1何去何从的并行计算 1

1.1.1忘掉那该死的并行 2

1.1.2可怕的现实:摩尔定律的失效 4

1.1.3柳暗花明:不断地前进 5

1.1.4光明或是黑暗 6

1.2你必须知道的几个概念 7

1.2.1同步(Synchronous)和异步(Asynchronous) 7

同步和异步通常用来形容一次方法调用。

同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。

异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。异步方法通常会在另外一个线程中“真实”地执行。整个过程,不会阻碍调用者的工作。

1.2.2并发(Concurrency)和并行(Parallelism) 8

并发和并行是两个非常容易被混淆的概念。它们都可以表示两个或者多个任务一起执行,但是侧重点有所不同。

并发偏重于多个任务交替执行,而多个任务之间有可能还是串行的。

并行是真正意义上的“同时执行”。

1.2.3临界区 9

临界区用来表示一种公共资源或者说共享数据,可以被多个线程使用。但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源就必须等待。

1.2.4阻塞(Blocking)和非阻塞(Non-Blocking) 9

形容多线程间的互相影响。比如一个线程占用了临界区资源,其他线程就必须等待,导致线程挂起,叫做阻塞。非阻塞强调没有一个线程可以妨碍其他线程执行。

1.2.5死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock) 10

死锁:两个或多个线程都在等待对方释放锁,导致线程都处于阻塞状态。

饥饿:一个或多个线程由于种种原因无法获得所需要的资源,导致一直无法执行。

活锁:线程都主动将资源释放给他人使用,导致资源不断在两个线程间跳动,却没有一个线程正常执行。

1.3并发级别 11

不同的控制并发的策略->并发级别

1.3.1阻塞 11

当使用synchronized关键字或者重入锁时,我们得到的就是阻塞线程,在其他线程释放资源之前当前线程都无法执行。

1.3.2无饥饿(Starvation-Free) 11

对于非公平锁来说线程调度倾向于满足高优先级的线程,可能导致低优先级的线程处于饥饿状态。

无饥饿就是保证线程都有机会执行。

1.3.3无障碍(Obstruction-Free) 12

乐观策略,认为多个线程之间的冲突几率不大,所有线程都无障碍的执行,检测到冲突后进行回滚。

不加锁,都进入临界区,数据不一致 回滚。

1.3.4无锁(Lock-Free) 13

无锁的并行都是无障碍的。但是,无锁的并发保证必然有一个线程能够在有限步内完成操作离开临界区。

1.3.5无等待(Wait-Free) 13

无等待则在无锁的基础上更进一步扩展。它要求所有的线程都必须在有限步内完成,这样就不会引起饥饿问题。一种典型的无等待结构就是RCU (Read Copy Update),读不加以控制,写修改副本,在合适的时机写回数据。

1.4有关并行的两个重要定律 14

1.4.1Amdahl定律 14

Amdahl定律:就是最后的加速比公式。加速比 = 优化前系统耗时 / 优化后的系统耗时,当处理器个数趋向与无穷大时,加速比和串行比例成反比。CPU数量越多,串行比列越小,则优化效果越好。

为了提高系统的速度,仅增加CPU处理器的数量并不一定能起到有效的作用。需要从根本上修改程序的串行行为,提高系统内可并行化的模块比重,在此基础上,合理增加并行处理器数量,才能以最小的投入,得到最大的加速比。

1.4.2Gustafson定律 16

**Gustafson定律:**S(n)=n-F(n-1) n为处理器个数,F为串行比例。

从Gustafson定律中,我们可以更容易地发现,如果串行化比例很小,并行化比例很大,那么加速比就是处理器的个数。只要不断地累加处理器,就能获得更快的速度。

1.4.3是否相互矛盾 17

Amdahl定律和Gustafson定律的结论不同是因为这两个定律对同一个客观事实从不同角度去审
视后的结果,不矛盾。

1.5回到Java:JMM 18

1.5.1原子性(Atomicity) 18

原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候, 一个操作一旦开始,就不会被其他线程干扰。

在32位JVM中,64位的long数据的读和写都不是原子操作。

1.5.2可见性(Visibility) 20

可见性是指当一个线程修改了某一个共享变量的值时,其他线程是否能够立即知道这个修改。

可见性问题是一个综合性问题。上面提到的缓存优化或者硬件优化(有些内存读写可能不会立即触发,而会先进一个硬件队列等待),指令重排(这个问题将在下一节中详细讨论)及编辑器的优化都会导致可见性问题。

1.5.3有序性(Ordering) 22

在多线程并发时,程序的执行就有可能出现乱序。有序性问题的原因是程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致。

指令重排是有一个基本前提的,就是保证串行语义的一致性。但是注意,没有义务保证多线程间的语义也一致。

指令重排的一个重要原因是出于性能的考虑。指令重排可以尽量少地中断CPU的流水线般运行指令。

1.5.4哪些指令不能重排:Happen-Before规则 27

指令重排不能违背的原则:

  • 程序顺序原则:一个线程内保证语义的串行性
  • volatile规则:volatile变量的写先于读
  • 锁规则:解锁在之后的加锁前
  • 传递性:A先于B,B先于C,则A必然在C前
  • 线程的start()方法先于它的其他动作
  • 线程的所有操作先于终结
  • 线程的中断先于被中断的代码
  • 对象的构造函数执行、结束先于finalize()方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值