兩個線程分別調用 setA() 和 setB(),兩方法內部均使用 synchronized(c) 同步塊(c 為共享的 Integer 對象)。日誌顯示線程交替輸出,甚至出現「搶到鎖」日誌打印後,另一線程的數據修改卻出現在同步塊內部的輸出中,令人困惑。
「搶到鎖」日誌語句位於 synchronized 塊之外。 線程進入方法、打印「搶到鎖」時,尚未獲得鎖;真正獲得鎖是在進入同步塊之後。因此日誌輸出順序無法反映實際的鎖獲取/釋放時序。
將日誌移入同步塊內部:
public void setA() {
synchronized(c) {
System.out.println(Thread.currentThread().getName() + " 真正獲得鎖 setA");
// ... 其餘邏輯
}
}
此時輸出將嚴格遵循互斥順序:一個線程完整執行同步塊後,另一線程才能進入。
synchronized(obj) 確保同一時刻僅有一個線程執行同步塊(同一鎖對象)。obj 可以是任意引用類型,但必須為同一實例。