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

Java 並發編程核心基石:共享性、互斥性、原子性、可見性、有序性深度講解

     編輯:Java 相關知識

Java 並發編程核心基石深度講解

並發編程是 Java 開發者最核心也最難掌握的技能之一,要求對計算機底層運行原理有深入理解。本文作為系列首篇,建立共享性、互斥性、原子性、可見性、有序性五大理論基石,後續文章將以此為基礎剖析 JUC 組件。

1. 共享性 — 線程安全問題根源

若所有數據僅在線程內有效,不存在線程安全問題。但多線程環境下數據共享不可避免(如數據庫數據)。

共享變量非線程安全演示

public class ShareData {
    public static int count = 0;
    public void addCount() { count++; } // 非原子操作
    // 10線程各執行100次,預期1000,實際遠小於1000
}

運行結果呈現數據競爭導致計數丟失。

2. 互斥性 — 解決共享寫衝突

資源互斥指同一時間僅允許一個訪問者訪問。讀操作可共享,寫操作需互斥。Java 提供 synchronized、Lock 實現互斥。

加鎖修正

public synchronized void addCount() { count++; } // 保證互斥,結果恆為1000

3. 原子性 — 操作不可分割

原子性指操作是獨立、不可分割的整體。i++ 實際分三步:讀取、加一、寫回,多線程下易產生競態條件。

保證原子性方案

  • 鎖:synchronized、ReentrantLock
  • CAS (Compare And Swap):樂觀鎖思想,比較預期值相同才更新,否則重試。缺陷:ABA 問題 (值變了又變回去)。

4. 可見性 — 線程間數據同步

JVM 內存模型:每個線程有工作內存 (對應 CPU 高速緩存),共享變量讀寫操作工作內存副本,稍後同步回主內存。導致線程 A 修改後,線程 B 可能讀不到最新值。

可見性問題演示

private static boolean ready = false;
private static int number = 0;
// Writer: number=100; ready=true;
// Reader: if(!ready) print(ready); print(number);
// 可能輸出 false 和 0 (可見性失效) 或 0 和 100 (重排序)

保證可見性

  • volatile:強制讀寫主內存,禁止指令重排序。
  • synchronized:解鎖前將工作內存刷新回主內存。

5. 有序性 — 指令重排序

為提升效能,編譯器/處理器/內存系統可能重排序指令:

  • 編譯器優化重排序
  • 指令級並行重排序 (ILP)
  • 內存系統重排序 (緩存/寫緩衝區)

JSR-133 經典案例

// 初始 x=y=0
// 線程1: x=1; r1=y;
// 線程2: y=1; r2=x;
// 可能結果: r1=0, r2=0 (發生重排序)

保證有序性

  • volatile:禁止重排序 (內存屏障)。
  • synchronized:鎖內代碼對外有序 (鎖語義)。
  • Happens-Before 規則:程序順序、鎖規則、volatile 規則、線程啟動/終止、傳遞性等。

總結

五大基石相互關聯:共享性引發問題,互斥性解決寫寫衝突,原子性保證操作完整,可見性保證讀寫同步,有序性防止重排序破壞邏輯。掌握這些理論,才能深入理解 JUC 組件設計原理。

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