首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

手寫筆記:synchronized vs Lock 核心區別與選型指南

     編輯:Java 綜合教學

並發控制兩大基石:內置鎖與顯式鎖的四大維度深度對比

面試高頻題、實戰選型依據。本文從 **實現層級、鎖粒度、獲取策略、條件變量** 四個維度,配合代碼片段,給出 synchronized 與 Lock 的本質區別與決策建議。

對比速覽表

維度synchronizedLock (ReentrantLock)
實現層級JVM 內置(字節碼 monitorenter/monitorexit)JDK API(AQS + CAS + Park/Unpark)
死鎖風險無法手動釋放,異常自動釋放需 finally 中 unlock(),否則極易死鎖
鎖粒度僅支持互斥鎖(獨佔)支持 ReadWriteLock:讀鎖共享、寫鎖獨佔、讀寫互斥
獲取策略阻塞式,無超時、無中斷、無輪詢tryLock() 非阻塞、tryLock(timeout) 定時、lockInterruptibly() 可中斷
條件變量wait/notify/notifyAll 單一條件newCondition() 多條件隊列,精準喚醒

代碼示例

1. Lock 釋放鎖必須在 finally

Lock lock = new ReentrantLock();
lock.lock();
try {
    // 臨界區
} finally {
    lock.unlock(); // 必須釋放,否則死鎖
}

2. ReadWriteLock 讀寫分離

ReadWriteLock rwl = new ReentrantReadWriteLock();
Lock r = rwl.readLock();  // 多線程可並發讀
Lock w = rwl.writeLock(); // 寫獨佔,讀寫互斥
r.lock();  try { /* 讀操作 */ } finally { r.unlock(); }
w.lock();  try { /* 寫操作 */ } finally { w.unlock(); }

3. tryLock 非阻塞嘗試

if (lock.tryLock()) {
    try { /* 獲取成功 */ } finally { lock.unlock(); }
} else {
    /* 未獲取到,執行降級邏輯或重試 */
}

4. Condition 多條件精準喚醒

Lock lock = new ReentrantLock();
Condition notFull  = lock.newCondition();
Condition notEmpty = lock.newCondition();
// 生產者
lock.lock(); try { while (full) notFull.await(); ... notEmpty.signal(); } finally { lock.unlock(); }
// 消費者
lock.lock(); try { while (empty) notEmpty.await(); ... notFull.signal(); } finally { lock.unlock(); }

選型建議

  • 簡單同步、代碼塊短、無特殊需求 → synchronized(JVM 優化好、可讀性強、自動釋放);
  • 需**讀寫分離**、高併發讀多寫少 → ReentrantReadWriteLock;
  • 需**超時獲取、可中斷、非阻塞嘗試** → ReentrantLock;
  • 需**多條件變量精準通知** → Lock + Condition;
  • JDK 1.6+ synchronized 引入偏向鎖、輕量級鎖、鎖消除等優化,性能差距已極小,優先考慮代碼簡潔性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved