synchronized 是 Java 並發編程的基石關鍵字,理解其鎖對象、作用域、可重入特性,是編寫正確高效併發代碼的前提。本文通過漸進式案例深度剖析。
public class SynDemo {
public void synMethod1() {
while (true) { sleep(1000); System.out.println("synMethod1"); }
}
public void synMethod2() {
while (true) { sleep(1000); System.out.println("synMethod2"); }
}
}
// 主程序啟動兩線程分別調用 synMethod1/2
// 輸出:交替打印 synMethod1、synMethod2、main...
兩線程並發無阻塞,CPU 時間片輪轉交替執行。
public synchronized void synMethod1() { ... }
public synchronized void synMethod2() { ... }
現象:只有 synMethod1 執行,synMethod2 永不執行。
原因:實例方法 synchronized 鎖的是 this (當前實例)。synMethod1 的 while(true) 永不退出,持有鎖不釋放,導致 synMethod2 無法獲取鎖而永久阻塞。
等價寫法:
public void synMethod1() {
synchronized (this) { while(true) { ... } }
}
public class SynDemo {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void synMethod1() {
synchronized (lock1) { while(true) { sleep(1000); System.out.println("synMethod1"); } }
}
public void synMethod2() {
synchronized (lock2) { while(true) { sleep(1000); System.out.println("synMethod2"); } }
}
}
效果:兩線程各自持有不同鎖,並發執行互不干擾,輸出交替出現 synMethod1、synMethod2。
| 維度 | 說明 |
|---|---|
| 鎖對象 | 實例方法鎖 this;靜態方法鎖 Class 對象;代碼塊鎖指定對象 |
| 可重入性 | 同一線程可重複獲取同一鎖 (計數器機制) |
| 內存可見性 | 解鎖前將工作內存刷新到主內存,獲取鎖後從主內存讀取,保證可见性 |
| 性能考量 | JDK 6+ 引入偏向鎖、輕量級鎖、鎖消除、鎖粗化等優化,性能大幅提升 |
private final Object lock = new Object(); 防止外部代碼獲取同一鎖造成死鎖或活鎖。java.util.concurrent.locks.ReentrantLock。tryLock(timeout)、減少嵌套鎖。static synchronized 與類鎖機制volatile 與 synchronized 協同:可見性 vs 原子性以上主題網上資源豐富,建議系統學習《Java 並發編程實戰》深入掌握。