实战java高并发程序设计之混淆概念理解

版权声明:转载注明出处 https://blog.csdn.net/nobody_1/article/details/82890223

摩尔定理失效引出的并发概念

摩尔定理:集成电路上可容纳的电晶体(晶体管)数目,约每隔24个月便会增加一倍;意思就是每两年,计算机性能就能翻一番。但摩尔定理不是自然规律,是根据原有数据预测出来的,因此当硬件的发展速度停滞不前摩尔定理自然也就失效。
摩尔定理的失效,使得科学家不得不寻找新的途径来满足越来越高的性能要求; CPU的性能受到单片机上晶体管数量的限制,那如果增加CPU上的独立的计算单元,是不是就能够提升处理速度,起到1+1等于甚至大于2的效果?事实证明,这是可以的,即多核CPU(多个CPU塞进一个CPU里面)。美国科学家唐纳德总结说:并发或多或少是由于硬件设计者无计可施导致的,他们将摩尔定理失效的责任推脱给软件开发者
所以,如何让多个CPU有效且正确地工作也就是一门技术。比如保证多线程之间的安全,如何理解线程间的无序性和可见性,如何将串行程序改为并行程序等。

并发世界里的几个概念

1. 同步和异步(通常用来形容一次方法调用)

同步:对同步方法的调用一旦开始,调用者必须等待调用结束返回后,才能继续执行;其他调用者若想调用此方法,则必须等上一调用者调用结束后才能调用同步方法。
异步:对异步方法的调用更像是信号的传递,一旦开始,方法调用立即返回,调用者可以继续后续的操作,而异步方法的执行则会在另外一个线程中“真实”的执行,方法执行完毕后则会通知调用者。

2. 并发和并行(表示任务执行方式)

并发强调任务的发生时刻是同时的,那么执行过程可能交替执行或者串行
并行强调任务的执行过程是同时的,是真正意义上的同时执行
举例:程序员应该多喝水,那么编码和喝水是两个任务,都由自己来执行;在某个时刻,正在编码的我们突然渴了,那么我们需要停下手头的编码,拿起水杯喝水,喝完水然后再继续编码,编码和喝水这个过程是交替执行,属于并发;如果我们有根吸管,那么喝水和编码则可以同时进行,互不影响,属于并行。(可以看出,并行要比并发消耗更多的资源)

3. 阻塞和非阻塞(形容多线程间的相互影响)

阻塞:如果一个线程占用了临界区资源,那么其他所有需要这个资源的线程就必须在这个临界区等待,等待会导致线程挂起,挂起的情况就是阻塞。
非阻塞:没有一个线程可以妨碍其他线程执行;多个线程竞争同一个资源,总会有一个线程成功,没有成功的线程不会挂起,而是等待或者尝试继续执行。

4. 死锁、活锁和饥饿

死锁:是指多线程相互占有各线程竞争的资源而导致的一种现象。
活锁:与死锁情况对立,在多任务执行过程中,当各线程意识到其他线程在请求自己拥有的资源时,各线程本着谦让的态度都释放资源,导致资源不断的在线程间跳动,使得线程无法访问资源的现象。
饥饿:某一个线程或者多个线程因为某种原因而无法获得所需要的资源,导致一直无法执行的现象。

并发级别

并发一般可以分为阻塞非阻塞两种,在某种程度上可以称为并发级别;理解并发级别对于理解并发算法和并发数据结构具有一定的帮助。

1. 阻塞级别

阻塞级别是最低级的并发级别,是指某线程访问被其他线程占有的临界资源,在资源未被释放之前,竞争资源的线程将被挂起,导致阻塞情况。一般基于锁(内置锁和重入锁)实现的线程都是阻塞线程。

2. 非阻塞级别

非阻塞级别可以分为无障碍、无锁、无等待

2.1 无障碍(Obstruction-Free)

无障碍级别是非阻塞级别中最弱的一种调度级别。无阻碍级别中的线程都可以进入临界资源,若某个线程遇到了资源竞争,且跟其他线程发生冲突导致资源的不一致,线程会回滚自己的才做并不断重试自己的操作;它能保证没有数据竞争时,线程必然在有限的步骤内执行完任务。

2.2 无锁(Lock-Free)

无锁级别是无障碍的且保证至少有一个线程能够竞争到资源。多线程同时进入临界区竞争临界资源,总会有一个线程能够胜出,其他未胜出的线程则不断重试,知道获取自己退出竞争。

2.3 无等待(Wait-Free)

无等待级别是无锁级别的更进一步。无锁级别保证至少一个线程能够竞争胜出,无等待级别则要求所有的线程都能够在有限步骤内完成操作,这样也就不会引起饥饿问题。
无等待级别的典型例子就是读写分离。读线程因为不会修改数据而采用无等待级别的线程,写线程则可以通过修改副本而互不影响,也可以使用无等待级别的线程。

并发性能的衡量标准

对于从串行程序到并发程序,性能提高是主要目的,那么如何衡量提高的标准?目前有两个定理可以量化这个标准:Amdahl定律Gustafson定律

1. Amdahl定律(阿姆达尔定理)

Amdahl定律定义了串行系统并行化后的加速比的计算公式和理论上限。
加速比定义:加速比 = 优化前系统耗时 / 优化后系统耗时
加速比值越高,表明优化效果越好。Amdahl定律公式如下:
在这里插入图片描述
注:图片来自《实战java高并发程序设计》
① 如果CPU处理器个数趋于无穷,那么加速比与串行化比率成反比;
② 可见加速比的大小与CPU的数量和串行化比率有关;仅提高CPU的数量,而不降低代码串行化比率,也无法提高系统的性能。

2. Gustafson定律(古斯塔夫森定律)

Gustafson定律也试图说明处理器个数、串行比例和加速比之间的关系,但是Gustafson定律和Amdahl定律的角度不同;同样,加速比都定义为优化前的系统耗时除以优化后的系统耗时。公式如下:
在这里插入图片描述
注:图片来自《实战java高并发程序设计》
可以看到,由于切入角度的不同,Gustafson定律的公式和Amdahl定律的公式截然不同。从Gustafson定律中,我们可以更容易地发现,如果串行化比例很小,并行化比例很大,那么加速比就是处理器的个数。只要你不断地累加处理器,就能获得更快的速度。

Amdahl强调:当串行比例一定时,加速比是有上限的,不管你堆叠多少个CPU参与计算,都不能突破这个上限
Gustafson定律关心的是:如果可被并行化的代码所占比重足够多,那么加速比就能随着CPU的数量线性增长

参考资料

《实战java高并发程序设计》

猜你喜欢

转载自blog.csdn.net/nobody_1/article/details/82890223