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

Java 並發核心:深度解析 synchronized、鎖優化與 Lock 體系

     編輯:Java 相關知識

一、synchronized 關鍵字

synchronized 是 Java 內置鎖,用於修飾方法或代碼塊,保證同一時刻只有一個線程執行該段代碼。分為兩種形式:

  • 同步方法:public synchronized void method(),鎖是當前實例對象(this)。
  • 同步代碼塊:synchronized(obj) { ... },鎖是括號內的對象,常用 this。

同步代碼塊優勢

縮小同步範圍(臨界區),只保護共享數據,提高並發性能。

synchronized(this) 關鍵特性

  1. 兩線程訪問同一對象的同步塊,同一時刻只能一個執行。
  2. 線程訪問同步塊時,其他線程仍可訪問該對象的非同步代碼。
  3. 線程持有對象鎖期間,其他線程訪問該對象所有同步塊均阻塞。

二、鎖的本質與分類

什麼是鎖?

生活中鎖保護門、箱子;Java 中鎖保護共享數據(堆中實例變量、方法區類變量)。JVM 為每個對象/類關聯一個監視器,監視器通過鎖實現排他訪問。

鎖的對象是什麼?

同步形式鎖對象
實例同步方法當前實例對象(this)
同步代碼塊括號內指定對象
靜態同步方法當前類的 Class 對象

經典錯誤:不同實例無法同步

public class ThreadTest implements Runnable {
    public synchronized void run() { ... }
    public static void main(String[] args) {
        for (int i=0; i<5; i++)
            new Thread(new ThreadTest()).start(); // 每次 new 新實例,鎖不同,無法同步!
    }
}

修正:共享同一實例 new Thread(sharedInstance),或使用 static 同步方法(鎖為 Class 對象)。

三、鎖升級機制(JDK 1.6+)

四種狀態:無鎖 → 偏向鎖 → 輕量級鎖 → 重量級鎖,隨競爭升級,不可降級。目標:提升獲取/釋放鎖效率。

  • 鎖自旋:線程不立即阻塞,循環等待鎖釋放,減少上下文切換開銷。
  • 偏向鎖:無競爭時,鎖偏向首個獲取線程,後續該線程進出同步塊無需 CAS,極低開銷。有競爭則撤銷偏向。
  • 輕量級鎖:線程棧幀建立鎖記錄,用 CAS 替換對象頭 Mark Word。無競爭時避免互斥量開銷;有競爭則膨脹為重量級鎖,反而更慢。
  • 鎖粗化:將多次細粒度鎖合併為一次粗粒度鎖,減少加/解鎖開銷。
  • 鎖消除:JIT 編譯器發現無共享數據競爭,直接刪除同步。

四、公平性與飢餓

飢餓成因:高優先級線程佔用 CPU、同步塊無序進入導致線程長期等待、wait() 隨機喚醒。

解決:使用公平鎖(如 ReentrantLock(true)),保證線程按請求順序獲取鎖。

五、可重入性

線程可重複獲得自己持有的鎖,計數器機制:獲取 +1,釋放 -1,歸零才真正釋放。避免父子類同步方法調用死鎖。

六、java.util.concurrent.locks 體系

提供比 synchronized 更靈活的鎖機制:

  • ReentrantLock:可重入互斥鎖,支持公平/非公平、可中斷、超時獲取、條件變量。
  • ReentrantReadWriteLock:讀寫分離,讀鎖共享、寫鎖獨占。
  • Condition:綁定鎖的條件等待/通知,替代 Object.wait/notify。
  • Semaphore:計數信號量,控制並發訪問數。
  • CyclicBarrier:屏障點同步,線程組相互等待。

七、總結

synchronized 經過 JDK 1.6 優化(偏向鎖、輕量級鎖、自旋、消除、粗化),性能大幅提升,代碼簡潔,首選。Lock 提供更豐富語義(公平、可中斷、條件變量),適用於複雜並發控制場景。理解鎖升級、可重入、公平性原理,是編寫高性能並發程序的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved