面試題:用java實(shí)現(xiàn)一個死鎖
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
實(shí)現(xiàn)一個最簡單的死鎖(Java版)
/**
* @author wall
* @date 2019/7/29 16:42
* @description 實(shí)現(xiàn)一個死鎖:A線程獲取B線程占有的鎖,B線程獲取A線程占有的鎖
*/
public class DeadLock {
//定義兩把鎖
private static ReentrantLock lockA = new ReentrantLock();
private static ReentrantLock lockB = new ReentrantLock();
//測試
public static void main(String[] args) {
//啟動線程A,B
new Thread(new A()).start();
new Thread(new B()).start();
}
static class A implements Runnable{
@Override
public void run() {
Thread.currentThread().setName("A線程");
//獲取鎖A
lockA.lock();
System.out.println(Thread.currentThread().getName()+"獲取鎖A");
//模擬業(yè)務(wù)操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//再獲取鎖B
lockB.lock();
System.out.println(Thread.currentThread().getName()+"獲取鎖B");
lockA.unlock();
lockB.unlock();
}
}
static class B implements Runnable{
@Override
public void run() {
Thread.currentThread().setName("B線程");
//獲取鎖B
lockB.lock();
System.out.println(Thread.currentThread().getName()+"獲取鎖B");
//模擬業(yè)務(wù)操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//再獲取鎖A
lockA.lock();
System.out.println(Thread.currentThread().getName()+"獲取鎖A");
}
}
}
產(chǎn)生死鎖的四大必要條件
避免死鎖的方式
銀行家算法
避免多次鎖定。盡量避免同一個線程對多個 Lock 進(jìn)行鎖定。例如上面的死鎖程序,主線程要對 A、B 兩個對象的 Lock 進(jìn)行鎖定,副線程也要對 A、B 兩個對象的 Lock 進(jìn)行鎖定,這就埋下了導(dǎo)致死鎖的隱患。
具有相同的加鎖順序。(給鎖添加順序)如果多個線程需要對多個 Lock 進(jìn)行鎖定,則應(yīng)該保證它們以相同的順序請求加鎖。比如上面的死鎖程序,主線程先對 A 對象的 Lock 加鎖,再對 B 對象的 Lock 加鎖;而副線程則先對 B 對象的 Lock 加鎖,再對 A 對象的 Lock 加鎖。這種加鎖順序很容易形成嵌套鎖定,進(jìn)而導(dǎo)致死鎖。如果讓主線程、副線程按照相同的順序加鎖,就可以避免這個問題。
使用定時(shí)鎖。程序在調(diào)用 acquire() 方法加鎖時(shí)可指定 timeout 參數(shù),該參數(shù)指定超過 timeout 秒后會自動釋放對 Lock 的鎖定,這樣就可以解開死鎖了。
死鎖檢測。死鎖檢測是一種依靠算法機(jī)制來實(shí)現(xiàn)的死鎖預(yù)防機(jī)制,它主要是針對那些不可能實(shí)現(xiàn)按序加鎖,也不能使用定時(shí)鎖的場景的。
死鎖的解除
版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:
https://blog.csdn.net/weixin_42228338/article/details/97686461



