Java 虛擬機通過 對象鎖 實現同步。每個對象(含 Class 對象與實例對象)天生擁有一把鎖及一個等待集。同步方法或同步塊在進入前必須獲取該鎖,釋放鎖時喚醒等待線程。
synchronized,鎖對象為 this(實例方法)或 Class 對象(靜態方法)。synchronized (lockObj) { ... },鎖對象由開發者指定,粒度更細。死鎖發生於多線程循環等待對方持有的鎖。典型場景:
// 線程 1
synchronized (lockA) {
synchronized (lockB) { ... }
}
// 線程 2
synchronized (lockB) {
synchronized (lockA) { ... }
}
避免策略:
tryLock(timeout) 代替無限等待。「粒度越小越好」並非絕對真理:
最佳實踐:針對熱點鎖進行壓測,在「鎖爭用度」與「關鍵區執行時間」間尋找平衡點。對於高併發計數器,優先考慮 LongAdder 或 AtomicLong 無鎖方案。
同步塊內可調用 wait() 釋放鎖並進入等待集,notify()/notifyAll() 喚醒。必須在持有鎖狀態下調用,否則拋 IllegalMonitorStateException。