Java 多線程編程中重要關鍵字 synchronized,實際依靠對象鎖機制實現線程同步。許多人困惑:「同步機制靠對象鎖,但關鍵字哪裡鎖住對象?」
public class ThreadTest extends Thread {
public synchronized void run() { ... } // 鎖住 this(每線程不同實例)
}
10 線程各持有自己實例的鎖,必然無同步效果。要同步,線程持有的對象鎖必須共享且唯一!
public class ThreadTest2 extends Thread {
private String lock;
public ThreadTest2(int threadNo, String lock) { this.lock = lock; }
public void run() {
synchronized (lock) { // 所有線程共享同一 String 物件
for (int i=1; i<10000; i++) System.out.println(...);
}
}
public static void main(String[] args) {
String lock = new String("lock");
for (int i=1; i<10; i++) new ThreadTest2(i, lock).start();
}
}
main 建立一 String 物件,透過構造函數傳給所有線程。Java 傳值特性使所有線程的 lock 變量指向堆中同一區域。同步塊鎖定同一物件 → 線程依序執行,同步生效。
public class ThreadTest3 extends Thread {
public static synchronized void abc(int threadNo) { ... }
public void run() { abc(threadNo); }
}
同步靜態方法的對象鎖是該類的 Class 實例。JVM 中所有被載入類有唯一類對象(本例 ThreadTest3.class),無論建立多少實例,類實例只有一個 → 同步生效。
| 同步方式 | 對象鎖 | 生效條件 |
|---|---|---|
| 同步實例方法 | 方法所在對象 (this) | 單例模式 |
| 同步靜態方法 | 類的 Class 物件 (唯一) | 總是生效 |
| 同步代碼塊 | synchronized(obj) 中的 obj | 程式設計師指定共享物件 |
synchronized(this) 僅單例模式生效synchronized 似在說:「給我一把鎖,我能創造一個規矩。」下一篇將介紹 JDK 5 的 java.util.concurrent 框架。