簡介
本文将通過Java代碼示範一個死鎖程式,并用JDK自帶的工具
jstack
工具,來驗證下是否真正的有死鎖發生。
一.什麼是死鎖
兩個或兩個以上的線程,互相持有對方需要的資源,導緻這些線程一直處于“等待”(WAITING)狀态。
二.死鎖的代碼示範
本例示範兩個線程,互相競争對方的對象鎖,造成的死鎖。
public class DeadLock implements Runnable {
int condition;
static Object object1 = new Object();
static Object object2 = new Object();
public static void main(String[] args) {
DeadLock deadLock1 = new DeadLock();
DeadLock deadLock2 = new DeadLock();
deadLock1.condition = 1;
deadLock2.condition = 2;
Thread t1 = new Thread(deadLock1);
Thread t2 = new Thread(deadLock2);
t1.start();
t2.start();
}
@Override
public void run() {
System.out.println("目前是線程:" + condition);
if (condition == 1) {
synchronized (object1) {
System.out.println("線程1" + "得到object1鎖");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程1,卡在下一行代碼");
synchronized (object2) {
System.out.println("列印出此行,表示線程1同時獲得兩把鎖");
}
System.out.println("線程1執行完畢");
}
}
if (condition == 2) {
synchronized (object2) {
System.out.println("線程2" + "得到object2鎖");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程2,卡在下一行代碼");
synchronized (object1) {
System.out.println("列印出此行,表示線程2同時獲得兩把鎖");
}
System.out.println("線程2執行完畢");
}
}
}
}
運作結果:
目前是線程:1
目前是線程:2
線程2得到object2鎖
線程1得到object1鎖
線程1,卡在下一行代碼
線程2,卡在下一行代碼
運作結果分析:
- 線程1持有了
的鎖,線程2持有了object1
的鎖。object2
- 然後線程1去競争
鎖;線程2去競争object2
鎖。object1
- 由于線程1并沒有釋放
鎖,線程2也并沒有釋放object1
鎖,是以會造成死鎖。object2
三.驗證是否真正死鎖
在指令行中輸入:
jps
,查到我們代碼程式的程序号為
6164
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNyZuBnLwYzNwAjNzYTM0EjMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
然後在指令行再輸入:
jstack -l 6164
,分析下程式狀态:
發現程式中出現了死鎖現象。
總結
明白了死鎖發生的機制,我們可以想辦法避免死鎖發生,第一種方法是注意加鎖順序,在上面的代碼執行個體中,我們隻要在兩個線程中,
對鎖的競争順序保持一緻(比如兩個線程都是先競争
object1
鎖,再競争
object2
鎖),那死鎖就不會出現了。第二種避免死鎖的方式是,
設定逾時時間,如果超過一定時間,自動釋放鎖。
在程式運作時,我們可以通過
jstack
工具,檢視程式運作狀态,是否有死鎖。