Java - 從例子中看如何解決死結(Dead lock)?
死結(Dead lock)定義:各執行緒間資源彼此交互取用,有機率造成「死結」(Dead lock)。
我們從例子中初步認識如何防止死結。
防止Dead lock例子:
package my11Test;
/**
*
* @author lucrecialin
*/
import java.util.concurrent.locks.*;
class Testing {
private ReentrantLock lock = new ReentrantLock();
private String name;
Testing(String name) {
this.name = name;
}
void doPrint(Testing test) {
System.out.printf("%s 和 %s 都有成功鎖定了。%n", this.name, test.name);
}
void doIt(Testing test) {
while (true) {
try {
if (lockAll(test)) {
doPrint(test);
break;
}
} finally {
unLockAll(test);
}
}
}
private boolean lockAll(Testing test) {
return this.lock.tryLock() && test.lock.tryLock();
}
private void unLockAll(Testing test) {
if (this.lock.isHeldByCurrentThread()) {
this.lock.unlock();
}
if (test.lock.isHeldByCurrentThread()) {
test.lock.unlock();
}
}
}
public class SolveDeadLock {
public static void main(String[] args) {
Testing test1 = new Testing("Testing1");
Testing test2 = new Testing("Testing2");
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
test1.doIt(test2);
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
test2.doIt(test1);
}
});
thread1.start();
thread2.start();
}
}
死結原因:
當test1物件呼叫doIt()時會鎖定test1物件,但因doIt()中嘗試呼叫test2物件的doPrint(),有機率無法取得該鎖定(如果test2物件也正呼叫doIt()時會鎖定test2物件),造成死結,反之亦然。
解法:
因為doIt()要成功執行完,需要test1和test2物件的鎖定,因而「確認兩物件皆成功鎖定後再執行程式」。
下面為編譯結果:
留言
張貼留言