建立基本的死鎖系統
當兩個競爭動作等待另一個完成時發生死鎖,因此兩者都沒有。在 java 中,每個物件都有一個鎖。為了避免單個物件上的多個執行緒進行併發修改,我們可以使用 synchronized
關鍵字,但一切都需要付出代價。錯誤地使用 synchronized
關鍵字會導致被稱為死鎖系統的卡住系統。
考慮在 1 個例項上有 2 個執行緒工作,讓我們將執行緒呼叫為 First 和 Second,並且假設我們有 2 個資源 R1 和 R2。首先獲得 R1 並且還需要 R2 完成,而 Second 獲得 R2 並需要 R1 完成。
所以說在時間 t = 0,
首先是 R1,第二個是 R2。現在第一個是等待 R2 而第二個等待 R1。這種等待是無限期的,這會導致僵局。
public class Example2 {
public static void main(String[] args) throws InterruptedException {
final DeadLock dl = new DeadLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
dl.methodA();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
dl.method2();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t1.setName("First");
t2.setName("Second");
t1.start();
t2.start();
}
}
class DeadLock {
Object mLock1 = new Object();
Object mLock2 = new Object();
public void methodA() {
System.out.println("methodA wait for mLock1 " + Thread.currentThread().getName());
synchronized (mLock1) {
System.out.println("methodA mLock1 acquired " + Thread.currentThread().getName());
try {
Thread.sleep(100);
method2();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void method2() throws InterruptedException {
System.out.println("method2 wait for mLock2 " + Thread.currentThread().getName());
synchronized (mLock2) {
System.out.println("method2 mLock2 acquired " + Thread.currentThread().getName());
Thread.sleep(100);
method3();
}
}
public void method3() throws InterruptedException {
System.out.println("method3 mLock1 "+ Thread.currentThread().getName());
synchronized (mLock1) {
System.out.println("method3 mLock1 acquired " + Thread.currentThread().getName());
}
}
}
該計劃的輸出:
methodA wait for mLock1 First
method2 wait for mLock2 Second
method2 mLock2 acquired Second
methodA mLock1 acquired First
method3 mLock1 Second
method2 wait for mLock2 First