死鎖的概念
“死鎖”指的是:
多個線程各自佔有一些共享資源,並且互相等待其他線程佔有的資源才能進行,而導致兩個或者多個線程都在等待對方釋放資源,都停止執行的情形。
因此, 某一個同步塊需要同時擁有“兩個以上對象的鎖”時,就可能會發生“死鎖”的問題。下面案例中,“化妝線程”需要同時擁有“鏡子對象”、“口紅對象”才能運行同步塊。那麼,實際運行時,“玉子的化妝線程”擁有了“鏡子對象”,“千反田的化妝線程”擁有了“口紅對象”,都在互相等待對方釋放資源,才能化妝。這樣,兩個線程就形成了互相等待,無法繼續運行的“死鎖狀態”。
public class DeadLock {
public static void main(String[] args) {
Markup g1 = new Markup(1, "玉子");
Markup g2 = new Markup(0, "千反田");
g1.start();
g2.start();
}
}
class Lipstck {
}
class Mirror {
}
class Markup extends Thread {
static Lipstck stick = new Lipstck();
static Mirror mirror = new Mirror();
int choice;
String girl;
public Markup(int choice, String girl) {
this.choice = choice;
this.girl = girl;
}
@Override
public void run() {
//化妝
markup();
}
//相互持有對方的對象鎖-->可能造成死鎖
private void markup() {
if(choice == 0) {
synchronized (stick) {
System.out.println(this.girl+"獲得口紅");
//2秒後想擁有鏡子的鎖
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror) {
System.out.println(this.girl+"照鏡子");
}
}
}
else {
synchronized (mirror) {
System.out.println(this.girl+"照鏡子");
//2秒後想擁有鏡子的鎖
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (stick) {
System.out.println(this.girl+"獲得口紅");
}
}
}
}
}
死鎖是由於“同步塊需要同時持有多個對象鎖造成”的,要解決這個問題,思路很簡單,就是:同一個代碼塊,不要同時持有兩個對象鎖。
改一下markup()方法,把鎖中鎖拿到外邊:
private void markup() {
if(choice == 0) {
synchronized (stick) {
System.out.println(this.girl+"獲得口紅");
//2秒後想擁有鏡子的鎖
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (mirror) {
System.out.println(this.girl+"照鏡子");
}
}
else {
synchronized (mirror) {
System.out.println(this.girl+"照鏡子");
//2秒後想擁有鏡子的鎖
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (stick) {
System.out.println(this.girl+"獲得口紅");
}
}
}