JDK 5 引入 java.util.concurrent.locks.Lock 接口,為並發編程提供了比內置鎖 synchronized 更豐富、更靈活的同步機制。本文從源碼、實現策略、選型建議、可中斷鎖實戰四個維度深度剖析。
public interface Lock {
void lock(); // 無條件獲取鎖
void lockInterruptibly() throws InterruptedException; // 可中斷獲取鎖
boolean tryLock(); // 非阻塞嘗試獲取鎖
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 定時嘗試
void unlock(); // 釋放鎖
Condition newCondition(); // 獲取條件變量(支持多條件等待)
}
lockInterruptibly() 允許等待線程響應中斷,提升系統靈活性。new ReentrantLock(true) 保證 FIFO 獲取鎖(吞吐率較低)。newCondition() 可創建多個 Condition,精準喚醒(如「不滿」喚醒生產者、「不空」喚醒消費者)。「除非需要 Lock 的高級特性,否則優先用 synchronized。」—— Brian Goetz
synchronized 隱式釋放鎖,杜絕忘記 unlock() 導致死鎖風險。synchronized 鎖持有者、等待隊列、死鎖鏈;Lock 鎖在 dump 中不可見。synchronized 是 JVM 內建屬性,未來優化空間大(如偏向鎖、輕量級鎖);Lock 基於 AQS,優化上限受限。// 標準 Lock 使用模式
Lock lock = new ReentrantLock(); // 或 new ReentrantLock(true) 公平鎖
lock.lock();
try {
// 臨界區操作
// 若有 return 必須放在 try 內
} finally {
lock.unlock(); // 必須在 finally 中釋放
}
// 可中斷鎖模式
lock.lockInterruptibly();
try {
// 耗時操作,可被中斷
} catch (InterruptedException e) {
// 處理中斷,恢復中斷狀態
Thread.currentThread().interrupt();
} finally {
if (lock.isHeldByCurrentThread()) lock.unlock();
}
場景:寫線程持有鎖 15 秒,讀線程等待 5 秒後被主線程中斷。
// 讀線程
synchronized (lock) {
System.out.println("start reading...");
}
// 主線程 sleep 5s 後 reader.interrupt()
// 結果:讀線程在 15 秒後才打印 "finish reading",中斷異常被吞噬/延遲
// 讀線程
lock.lockInterruptibly();
try {
System.out.println("start reading...");
} finally {
lock.unlock();
}
// 主線程 sleep 5s 後 reader.interrupt()
// 結果:讀線程 5 秒處拋出 InterruptedException,打印 "interrupt reading",不再等待寫線程

| 場景 | 推薦 | 理由 |
|---|---|---|
| 簡單同步、臨界區短 | synchronized | 代碼簡潔、JVM 優化充分、無死鎖風險 |
| 需響應中斷(取消任務、超時控制) | ReentrantLock.lockInterruptibly() | 唯一標準 API 實現可中斷獲取鎖 |
| 需公平調度(避免線程饑餓) | new ReentrantLock(true) | synchronized 非公平,Lock 可選公平 |
| 複雜等待/通知邏輯(多條件) | Lock + 多個 Condition | synchronized 僅支持單一 wait/notify |
| 跨方法/跨塊加鎖 | Lock | 非塊結構靈活性 |
Lock 機制通過 AQS 實現了用戶態非阻塞同步,賦予了可中斷、公平、多條件等高級能力,是構建高性能並發組件(如 ReentrantReadWriteLock、Semaphore、CountDownLatch)的基石。但日常業務開發中,synchronized 因其簡單性、安全性、可診斷性及 JVM 持續優化,仍是首選。掌握兩者差異,按需選型,方為並發編程正道。