几个并发的重要概念
- 同步和异步
- 并发和并行
- 临界区
- 阻塞和非阻塞
- 阻塞&非阻塞,同步&异步
- 死锁、活锁、饥饿
- 并行级别
同步和异步
- 同步交互:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有一个等待的过程(哪些情况需要使用同步呢?比如银行的转账系统)
- 异步交互:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待
- 区别:一个需要等待,一个不需要等待,在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。
并发和并行
例子:
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
例子来源:并发与并行的区别? - 知乎用户的回答 - 知乎
https://www.zhihu.com/question/33515481/answer/58849148
临界区
临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用。但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源,就必须等待
阻塞和非阻塞
- 阻塞和非阻塞通常用来形容多线程间的相互影响。比如一个线程占用了临界区资源,那么其他所有需要这个资源的线程就必须在这个临界区中进行等待,等待会导致线程挂起。这种情况就是阻塞。比如,如果占用资源的线程一直不愿意释放资源,那么其他所有阻塞在这个临界区上的线程都不能工作。
- 非阻塞允许多个线程同时进入临界区
阻塞&非阻塞,同步&异步
老张爱喝茶,废话不说,煮开水。
出厂任务:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)
- 老张把水壶放在火上,立等水开。【同步阻塞】
- 老张觉得自己有点傻
- 老张把水壶放在火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
- 老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀嘀嘀~~~~的噪声的。
- 老张把响水壶放在火上,立等水开。【异步阻塞】
- 老张觉得这样傻等的意义不大
- 老张把响水壶放在火上,去客厅看电视,水壶响之前不再去看它了 ,响了再去拿水壶。【一部非阻塞】
- 老张觉得自己聪明了。
所谓同步和异步,只是对于水壶而言。
普通水壶,同步;响水壶,异步
虽然都能干活儿,但是响水壶可以在自己干完活之后,提示老张水开了
同步只能让调用者去轮训自己,造成老张效率低下。
所谓阻塞和非阻塞,仅仅对于老张而言。
立等的老张,阻塞;看电视的老张,非阻塞
例子来源:怎样理解阻塞非阻塞与同步异步的区别? - 愚抄的回答 - 知乎
https://www.zhihu.com/question/19732473/answer/23434554
死锁、活锁和饥饿
死锁
-
概念
- 是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在相互等待的进程称为死锁进程。
-
死锁发生的条件
- 互斥条件:线程对资源的访问是排他性的,如果一个线程占用了某个资源,那么其他线程必须处于等待状态,直到资源被释放。
- 请求和保持条件:线程T1至少已经保持了一个资源R1占用,但又提出了对另一个资源R2请求,而此时,资源R2被其他线程T2占用,于是该线程T1也必须等待,但又对自己保持的资源R1不释放。
- 不剥夺条件:线程已获得的资源,在未使用完之前,不能被其他线程剥夺,只能在使用完之后自己释放。
- 环路等待条件:如下图中的小汽车
活锁
活锁是指线程1可以使用资源,但它很礼貌,让其他线程先使用资源,线程2也可以使用资源,但它很绅士,也让其他线程先使用资源。这样你让我,我让你,最后两个线程都无法使用资源。
活锁例子:
马路中间有条小桥,只能容纳一辆车经过,桥两头开来两辆车A和B,A比较礼貌,示意B先过,B也比较礼貌,示意A先过,结果两人一直谦让谁也过不去。
饥饿
是指如果线程T1占用了资源R,线程T2又请求封锁R,于是T2等待。T3也请求资源R,当T1释放了R上的封锁后,系统首先批准了R3的请求,T2仍然等待。然后T4又请求封锁R,当T3释放了R上的封锁之后,系统又批准了T4的请求。。。。。T2就一直在等待,就一直在饿着。O.O
并行的级别
-
阻塞
-
非阻塞(宽进严出的策略)
- 无障碍
- 无锁
- 无等待
-
无障碍
- 无障碍是一种最弱的非阻塞调度
- 自由出入临界区
- 无竞争时,有限步内完成操作
- 有竞争时,回滚数据
-
无锁
- 是无障碍的
- 保证有一个线程可以胜出
while(!atomicVar.compareAndSet(localVar, localVar+1){
localVar = atomicVar.get();
}
- 无等待
- 无等待是无锁的
- 要求所有的线程都必须在有限步内完成
- 无饥饿的