龙空技术网

JAVA校招题基础知识点复习第五天(经典问题:如何避免死锁)

自学Java的皮卡丘 91

前言:

今天各位老铁们对“java死锁避免”大概比较着重,我们都需要知道一些“java死锁避免”的相关资讯。那么小编也在网上收集了一些有关“java死锁避免””的相关文章,希望兄弟们能喜欢,各位老铁们一起来学习一下吧!

如何确保N个线程可以访问N个资源同时又不导致死锁?

要想弄清这个问题,我们必须先要知道什么是死锁,死锁产生的条件又有哪些?

所谓死锁就是指多个线程因竞争资源而造成的一种"僵局",即相互等待。若没有外力作用,这些进程都将无法向前运行推进下去。

死锁产生示意图

弄清楚了什么是死锁,接下来我们来看看死锁产生的必要条件有哪些?

要产生死锁就必须要同时满足四个条件,只要其中一个条件不成立,死锁就不会产生。反过来说,只要破坏了这四个条件中的任何一个,我们就可以避免死锁。

(1)互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。通俗来说就是一个资源每次只能被一个进程使用。独木桥每次只能通过一个人。

(2)不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。相当于就是进程已获得的资源,在未使用完之前,不能强行剥夺。甲不能强制乙退出桥面,乙也不能强制甲退出桥面。

(3)请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。即,一个进程因请求资源而阻塞时,对已获得的资源保持不放。乙不退出桥面,甲也不退出桥面。

(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。如果乙不退出桥面,甲不能通过,甲不退出桥面,乙不能通过。

循环等待示意图

因为线程互斥基本无法比避免,所以一般采用以下三种方法来避免死锁:

1、指定加锁顺序。所有线程按照相同的顺序获得资源的锁,不先获得顺序靠前的锁,无法获得后续的锁。则先获得锁的线程不会请求后获得锁的线程占用的资源,因为后获得锁的线程还没能获得先获得锁的线程未释放的锁,更无法占用先获得锁的线程还没获得的顺序靠后的锁。缺点:需要手动对锁的获得顺序进行分析。

2、指定加锁时限:线程指定超时时间,若无法获得锁的占用权,进行回退操作,并释放已占用的锁,经一段延时后再尝试进行任务。缺点:线程过多的话,可能造成频繁回退,运行效率不高。

3、死锁检测:将线程和已获得锁的情况记录下来,定时检测是否所有死锁现象(线程循环等待现象),回退处于死锁状态的线程,延时后,重试这些线程,与添加加锁时限类似,缺点也同。

标签: #java死锁避免