一.概念
1、 为什么要并发?
比如因为IO操作遇到了阻塞,CPU可以转去执行其他线程,这时并发的优点就显示出来了:更高效的利用CPU,提高程序的响应速度。
Java的线程机制是抢占式的,会为每个线程分配时间片。

2、 并行与并发

1) 并发就是在单核处理中同时处理多个任务。(这里的同时指的是逻辑上的同时)

2) 并行就是在多核处理器中同时处理多个任务。(这里的同时指的就是物理上的同时)

Java并行机制的特点 java程序的并行机制_无锁


并发偏重于多个任务交替执行,而多个任务之间有可能还是串行的。而并行是真正意义上的“同时执行”。严格意义上来说,并行的多个任务是真实的同时执行,而对于并发来说,这个过程只是交替的,一会儿运行任务A一会儿执行任务B,系统会不停地在两者间切换。但对于外部观察者来说,即使多个任务之间是串行并发的,也会造成多任务间是并行执行的错觉。真实的并行也只可能出现在拥有多个CPU的系统中(比如多核CPU)。3、同步和异步

所谓同步,就是在发出一个”调用”时,在没有得到结果之前,该”调用”就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由”调用者”主动等待这个”调用”的结果。

而异步则是相反,”调用”在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在”调用”发出后,”被调用者”通过状态、通知来通知调用者,或通过回调函数处理这个调用。

Java并行机制的特点 java程序的并行机制_Java并行机制的特点_02

4、 临界区

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

Java并行机制的特点 java程序的并行机制_临界区_03

5、 阻塞和非阻塞
阻塞和非阻塞通道用来形容多线程间的相互影响。比如一个线程占用了临界区资源,那么其它所有需要这个资源的线程就必须在这个临界区中进行等待,待待会导致县城挂起,这种情况就是阻塞,此时,如果占用资源的线程一直不愿意释放资源,那么其它所有阻塞在这个临界区上的线程都不能工作。
非阻塞允许多个线程同时进入临界区。

6、死锁、饥饿和活锁
死锁饥饿和活锁都是用来形容多线程的活跃性。
死锁:是指两个或者两个以上的进程执行过程中,由于竞争资源或者由于彼此通信而造成的一种堵塞的现象,若无外力的作用,他们都将无法推进下去。
饥饿:是指线程一直无法获取资源,导致一个堵塞。例如可能是因为优先级太低,而高优先级的线程一直抢占它需要的资源导致低级线程无法工作。
活锁:是指任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。

7、并行的级别
由于临界区的存在,多线程之间的并发必须受到控制。根据控制并发的策略,我们可以把并发的级别进行分类,大致上可以分为阻塞、无障碍、无锁、无等待几种。而无障碍、无锁、无等待就是非阻塞的。
阻塞调度是一种悲观的策略,认为大家修改数据会把数据改乱,每次只能一个人去修改数据;非阻塞调度是一种乐观的,宽进严出的策略,进的时候都可以进,如果发现一个线程在临界区遇到了资源竞争,跟别人产生了冲突就会回滚这条数据,重新做这条操作。

1)堵塞(Blocking)
一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。

2)无障碍(Obstruction-Free)
表示所有线程都可以访问临界区,为了保证数据安全,如果线程发生冲突就回滚。
无障碍是一种最弱的非阻塞调度
自由出入临界区
无竞争时,有限步内完成操作
有竞争时,回滚数据

3)无锁(Lock-Free)
在无锁的情况下,所有的线程都能尝试对临界区进行访问,但不同的是,无锁的并发保证必然有一个线程能够在有限步内完成操作离开临界区。

while(!atomicVar.compareAndSet(localVar,localVar+1))
{
   localVar = atomicVar.get();
}

4)无等待(Wait-Free)
无锁只要求有一个线程可以在有限步内完成操作,而无等待则在无锁的基础上更进一步进行扩展。它要求所有的线程都必须在有限步内完成,这样就不会引起饥饿问题。如果限制这个步骤上限,还可以进一步分解为有界无等待和线程数无关的无等待几种,它们之间的区别只是对循环次数的限制不同。即无等待需要具备以下三个条件:
a. 无锁的
b. 要求所有的线程都必须在有限步内完成
c. 无饥饿的

二、有关并行的2个重要定律
1、 Amdahl定律(阿姆达尔定律)
定义了串行系统并行化后的加速比的计算公式和理论上限
加速比定义:加速比=优化前系统耗时、优化后系统耗时

增加CPU处理器的数量并不一定能起到有效的作用,提高系统内可并行化的模块比重,合理增加并行处理器数量,才能以最小投入,得到最大的加速比。
2、 Gustafson定律(古斯塔夫森定律)
说明处理器个数,串行比例和加速比之间的关系。
只要有足够的并行化,那么加速比和CPU个数成正比。