死瑣
A線程持有a鎖,等待獲取b鎖;同時(shí)B線程持有b鎖,等待獲取a鎖。
死瑣條件
-- 獨(dú)占鎖:
- 互斥:資源不能被共享,只能由一個(gè)進(jìn)程使用。
- 請(qǐng)求與保持:進(jìn)程已獲得了一些資源,但因請(qǐng)求其它資源被阻塞時(shí),對(duì)已獲得的資源保持不放。
- 不可搶占:有些系統(tǒng)資源是不可搶占的,當(dāng)某個(gè)進(jìn)程已獲得這種資源后,系統(tǒng)不能強(qiáng)行收回,只能由進(jìn)程使用完時(shí)自己釋放。
-- 循環(huán)等待:若干個(gè)進(jìn)程形成環(huán)形鏈,每個(gè)都占用對(duì)方申請(qǐng)的下一個(gè)資源。
public static void main(String[] args) {
final Object a = new Object();
final Object b = new Object();
Thread threadA = new Thread(() -> {
synchronized (a) { //sleep 下可以確保死鎖
System.out.println("now i in threadA-locka");
synchronized (b) {
System.out.println("now i in threadA-lockb");
}
}
});
Thread threadB = new Thread(() -> {
synchronized (b) { //sleep 下可以確保死鎖
System.out.println("now i in threadB-lockb");
synchronized (a) {
System.out.println("now i in threadB-locka");
}
}
});
threadA.start();
threadB.start();
}
如何避免
- 避免多個(gè)線程互相持有對(duì)方線程所需要的獨(dú)占鎖的的情況
- 設(shè)置優(yōu)先級(jí)
- 超時(shí)放棄
ReentrantLock接口中: boolean tryLock(long time, TimeUnit unit)
設(shè)置超時(shí)時(shí)間,超時(shí)可以退出防止死鎖。
- 特定順序 A->B->C
- 盡量降低鎖的使用粒度,盡量不要幾個(gè)功能用同一把鎖,能鎖塊不鎖方法
- 不要用鎖
- 用Concurrent類。比較常用的是ConcurrentHashMap、ConcurrentLinkedQueue、
原子操作。AtomicBoolean等,實(shí)際應(yīng)用中java.util.concurrent.atomic十分有用,簡(jiǎn)單方便且效率比使用Lock更高
銀行家算法
- 條件:
- 固定數(shù)量的進(jìn)程,固定數(shù)量的資源
- 進(jìn)程預(yù)先指定工作所需最大資源
- 進(jìn)程不能申請(qǐng)比總資源還多的資源
- 進(jìn)程等待時(shí)間有限
- 進(jìn)程在有限時(shí)間使用資源,用完歸還
符號(hào):
Available 系統(tǒng)可用資源數(shù)
Max[i] 進(jìn)程i對(duì)資源的最大需求
Allocation[i] 進(jìn)程i得到的資源數(shù)
Need[i] 進(jìn)程i還需要的資源數(shù)
Request[i] 進(jìn)程i當(dāng)前申請(qǐng)的資源數(shù)步驟:
- Request[i] <= need[i]
- Request[i] <= Available
- 分配資源,調(diào)整狀態(tài)
Available = Available - Request[i]
Allocation[i] = Allocation[i] + Request[i]
Need[i] = Need[i] - Request[i] - 判斷新?tīng)顟B(tài)是否有效,無(wú)效則退回,進(jìn)程等待
初始化:Work = Available, finished = false
檢測(cè):Need[i] <= Work
檢測(cè)死鎖
-
jstack
Jstack工具可以用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照。線程快照是當(dāng)前java虛擬機(jī)內(nèi)每一條線程正在執(zhí)行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現(xiàn)長(zhǎng)時(shí)間停頓的原因,如線程間死鎖、死循環(huán)、請(qǐng)求外部資源導(dǎo)致的長(zhǎng)時(shí)間等待等。
jps 查端口號(hào)
jstack pid
-
jconsole
圖形化工具