今天看到一段關于synchronized的小代碼,比較有意思。當將S1的static去掉,這個死鎖便解開了。其實也很好理解,線程1進入后鎖住S1,并且等待了500,在等待時線程2來了,鎖住了S2。線程1的500過了后接著鎖住S2開始下面的輸出,但是S2被線程2鎖住不放;同樣線程2鎖住了S2,接著去取S1的控制權,但是線程1卻握著不放。死鎖便產生了。S1和S2都是static關鍵字修飾,他們都是共享內存空間,去掉這個關鍵字,那么線程1和線程2鎖住的不是同一個對象了,問題也不會產生。每個對象都包含了一把鎖(也叫作“監視器”),它自動成為對象的一部分(不必為此寫任何特殊的代碼)。調用任何synchronized方法時,對象就會被鎖定,不可再調用那個對象的其他任何synchronized方法,除非第一個方法完成了自己的工作,并解除鎖定。
package com.example.thread2;
public class TestDeadLock implements Runnable {
public int flag = 1;
static Object S1 = new Object();
static Object S2 = new Object();
public String threadId;
public TestDeadLock(String s){
threadId = s;
}
public void run() {
System.out.println(threadId + ":flag=" + flag);
if (flag == 1) {
synchronized (S1) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (S2) {
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (S2) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (S1) {
System.out.println("0");
}
}
}
}
public static void main(String[] args) {
TestDeadLock td1 = new TestDeadLock("No.1");
TestDeadLock td2 = new TestDeadLock("No.2");
td1.flag = 1;
td2.flag = 0;
Thread t1 = new Thread(td1);
Thread t2 = new Thread(td2);
t1.start();
t2.start();
}
}