一、前言
1、为什么需要并行?
-业务需求(业务上需要一个逻辑单元,多个线程并行执行,例如JVM虚拟机;GC线程、main线程、业务线程等);
-性能(本课程主要探讨原因,多线程性能更好,是相对的;在多核CPU上确实性能很好,服务端编程提高性能);
并行代码比串行代码复杂很多;
Linus torvalids:并行计算主要在图像处理和服务端编程2个领域使用;
-摩尔定律失效:预计18个月芯片的性能会提高一倍;10年过去了,CPU的主频还停留在4GHZ。
无法提高单核CPU的频率性能,所以在CPU中放多个核来提高性能。使用并行来提高多核性能,要注意多核问题。
2、几个重要的概念
-同步和异步
同步:方法调用之后。会等待方法返回;
异步:方法调用之后会立即返回,后台另起一个线程等待返回结果;可以继续执行其他方法;
-并发和并行:一般不需要刻意区分,外界表现基本是一致的;
并行(Parallelism):两个线程(进程)同时执行。单核不存在并行。
并发(concurrency):一个线程(进程)不停的切换,有调度的过程。
-临界区:公共资源、共享数据,可被多个线程访问。需要被控制的区域,防止数据被多个线程操作出现问题。资源被占用后,其他访问线程进入等待队列。
-阻塞和非阻塞:形容多线程间的相互影响
阻塞(Blocking):如一个线程占用了临界区资源,其它线程必须在临界区进行等待,线程挂起。交个操作系统调度,性能不会太好,线程上下文切换通常需要八万个时钟周期来处理。
非阻塞(Non-blocking):非阻塞允许多个线程同时进入临界区;
-锁、饥饿和活锁
死锁(Deadlock):纸和笔问题、哲学家就餐问题,抢占了资源不释放,死锁程序线程卡死,静态问题,CPU占用0,;
饥饿(starvation):抢占资源时,操作系统一直调度不到一些优先级比较低的线程;原子操作,回旋锁,CAS操作,总是失败,可能会饿死;
活锁(livelock):电梯问题,活动的死锁;同时抢占资源、同时释放资源,动态问题,不好排查。
-并行的级别
a阻塞; 非阻塞(b无障碍、c无锁、d无等待);
无障碍(Obstruction-Free ):最弱的非阻塞调度,所有你线程自由出入临界区;宽进严出,无竞争时有限步完成,有竞争时若有冲突,回滚数聚;
无锁(Lock-Free ):无障碍的,保证一个线程可以胜出;比如CAS
无等待(Wait-Free ):无锁的,所有的线程在有限步内完成,无饥饿的;非阻塞最高级别的;读操作是无等待的,优化写操作达到无等待(复制写区域,然后复制回去,指针操作迅速)。
3、并行的两个重要定律:
Amdahl定律(阿姆达尔定律) :定义了串行系统并行化后的加速比计算公式和理论上限;加速比=优化前耗时/优化后耗时;增加CPU处理器数量并不一定起到有效作用,提高系统内可并行化的模块比重,合理增加处理器数量,才是最小的投入,得到最大加速比;
Gustafson定律(古斯塔夫森) :说明了处理器个数,串行比例和加速比之间的关系;只要足够的并行化,那么加速比和CPU个数成正比;