synchronized 是 Java 並發編程的基石,通過監視器鎖實現線程互斥。本文系統梳理其四種鎖形式與兩種同步塊用法,並附帶經典計數器實戰案例。
同步塊鎖定特定對象(監視器),同一時刻僅允許一個線程持有該鎖進入同步代碼區,其他線程阻塞等待。
| 形式 | 代碼示例 | 鎖對象 | 作用範圍 |
|---|---|---|---|
| 實例方法同步 | public synchronized void add() | 當前實例 (this) | 同一實例的所有同步實例方法互斥 |
| 靜態方法同步 | public static synchronized void add() | 類對象 (MyClass.class) | 同一類的所有同步靜態方法互斥 |
| 實例方法同步塊 | synchronized(this) { ... } | 指定實例 (通常是 this) | 細粒度控制,僅同步關鍵代碼段 |
| 靜態方法同步塊 | synchronized(MyClass.class) { ... } | 指定類對象 | 靜態上下文細粒度同步 |
this,靜態方法用 ClassName.class,也可用私有 final Object lock = new Object() 封裝鎖public class Counter {
private long count = 0;
// 同步實例方法,鎖住當前 Counter 實例
public synchronized void add(long value) {
this.count += value;
}
}
public class CounterThread extends Thread {
private Counter counter;
public CounterThread(Counter counter) { this.counter = counter; }
@Override
public void run() {
for (int i = 0; i < 10; i++) counter.add(i);
}
}
// 測試:共享同一實例 → 線程串行執行 add()
Counter counter = new Counter();
new CounterThread(counter).start();
new CounterThread(counter).start();
// 對比:不同實例 → 線程並行執行,無阻塞
Counter counterA = new Counter(), counterB = new Counter();
new CounterThread(counterA).start();
new CounterThread(counterB).start();
掌握 synchronized 的鎖對象語義與作用範圍,是編寫正確、高效並發程序的前提。實戰中建議優先使用同步塊配合私有鎖對象,實現最小化同步粒度。