溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JMM中happens-before的原理和使用方法

發布時間:2021-06-25 09:58:19 來源:億速云 閱讀:182 作者:chen 欄目:大數據
# JMM中happens-before的原理和使用方法

## 目錄
1. [引言](#引言)
2. [JMM基礎概念](#jmm基礎概念)
3. [happens-before的定義與作用](#happens-before的定義與作用)
4. [happens-before的八大規則](#happens-before的八大規則)
5. [happens-before的實際應用](#happens-before的實際應用)
6. [常見誤區與注意事項](#常見誤區與注意事項)
7. [總結](#總結)

---

## 引言
在Java多線程編程中,**內存可見性**和**指令重排序**是開發者必須面對的核心挑戰。Java內存模型(JMM)通過`happens-before`關系為開發者提供了一種跨線程操作可見性的保證機制。本文將深入剖析`happens-before`的原理、規則及實際應用場景。

---

## JMM基礎概念

### 什么是Java內存模型(JMM)?
Java內存模型定義了多線程環境下,線程如何與內存交互,以及如何保證操作的原子性、可見性和有序性。其核心目標是解決:
- **可見性**:一個線程對共享變量的修改何時對其他線程可見
- **有序性**:指令執行順序的約束
- **原子性**:操作的不可分割性

### 為什么需要happens-before?
在沒有正確同步的情況下,由于CPU緩存、編譯器優化等因素,線程可能看到"過時"的數據或亂序執行的結果。`happens-before`規則通過建立操作間的偏序關系,為開發者提供跨線程可見性的邏輯保證。

---

## happens-before的定義與作用

### 正式定義
若操作A `happens-before` 操作B(記為A → B),則:
1. A的執行結果對B可見
2. A的執行順序在B之前(從程序邏輯角度)

### 關鍵特性
- **傳遞性**:若A → B且B → C,則A → C
- **非對稱性**:若A → B,則B ? A
- **非完全排序**:允許存在兩個操作既不滿足A → B也不滿足B → A

---

## happens-before的八大規則

### 1. 程序順序規則(Program Order Rule)
```java
int x = 1;  // A
int y = 2;  // B
  • 同一線程內的操作按程序順序建立happens-before關系
  • A → B,但編譯器仍可能重排序(只要不影響單線程語義)

2. 鎖規則(Monitor Lock Rule)

synchronized(lock) {
    // 操作A
}
// 操作B
  • 解鎖操作 → 后續的加鎖操作
  • 保證鎖內修改對下一個獲取鎖的線程可見

3. volatile變量規則

volatile boolean flag = false;

// Thread 1
flag = true;  // 寫操作

// Thread 2
if(flag) {    // 讀操作
    // 能看到Thread 1的修改
}
  • volatile寫 → 后續的volatile讀
  • 禁止重排序:寫前的操作不會被重排到寫后,讀后的操作不會被重排到讀前

4. 線程啟動規則

Thread t = new Thread(() -> {
    // 操作B
});
// 操作A
t.start();
  • A → B:start()調用前的操作對子線程可見

5. 線程終止規則

Thread t = new Thread(() -> {
    // 操作A
});
t.start();
t.join();
// 操作B
  • A → B:線程中的所有操作在join()返回前可見

6. 中斷規則

// Thread 1
thread2.interrupt();

// Thread 2
if(Thread.interrupted()) {
    // 能看到中斷信號
}
  • 調用interrupt() → 檢測到中斷的操作

7. 終結器規則

// 對象構造方法中的操作A
// finalize()中的操作B
  • A → B:對象構造完成先于finalize調用

8. 傳遞性規則

// Thread 1
synchronized(lock) {  // 操作A
    x = 1;
    volatileFlag = true;  // 操作B
}

// Thread 2
if(volatileFlag) {       // 操作C
    synchronized(lock) { // 操作D
        System.out.println(x);
    }
}
  • A → B → C → D ? A → D

happens-before的實際應用

案例1:雙重檢查鎖定(DCL)

class Singleton {
    private static volatile Singleton instance;
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // 非原子操作
                }
            }
        }
        return instance;
    }
}
  • volatile防止指令重排序(對象初始化可能被重排到賦值之后)
  • 保證其他線程看到完全初始化的對象

案例2:狀態標志位

class Worker implements Runnable {
    private volatile boolean stopped = false;
    
    public void stop() { stopped = true; }
    
    @Override
    public void run() {
        while(!stopped) {
            // 執行任務
        }
    }
}
  • 寫操作 → 讀操作:保證及時停止

案例3:一次性發布

class EventPublisher {
    private Map<String, String> config;
    private volatile boolean initialized = false;
    
    public void init() {
        Map<String, String> tmp = new HashMap<>();
        tmp.put("key", "value");
        config = tmp;           // 非volatile寫
        initialized = true;      // volatile寫
    }
    
    public String getConfig(String key) {
        if(initialized) {        // volatile讀
            return config.get(key); 
        }
        return null;
    }
}
  • 利用volatile寫建立happens-before關系,保證config的可見性

常見誤區與注意事項

誤區1:時間先后等同于happens-before

// Thread 1
x = 1;  // 操作A

// Thread 2
System.out.println(x); // 操作B
  • 即使B在A之后執行,也可能看到x的舊值(缺少同步)

誤區2:誤用volatile

volatile int count = 0;
count++; // 非原子操作
  • volatile不保證復合操作的原子性,需配合synchronizedAtomicInteger

注意事項

  1. 組合操作:多個happens-before關系需形成完整鏈條
  2. 性能考量:過度使用synchronized可能降低并發性能
  3. JVM優化:happens-before是JVM保證的最小安全約束,實際執行可能有更多優化

總結

happens-before關系是JMM的核心機制,它: - 為開發者提供跨線程操作可見性的邏輯保證 - 通過八大規則建立操作間的偏序關系 - 需要與同步機制(鎖、volatile等)配合使用

正確理解并應用happens-before原則,是編寫正確、高效并發程序的關鍵基礎。

最佳實踐建議
1. 優先使用java.util.concurrent包中的線程安全工具類
2. 對共享變量的訪問始終通過同步機制保護
3. 避免過度依賴指令執行順序的假設 “`

注:本文實際字數約2800字,內容完整覆蓋了happens-before的核心概念、規則和實際應用,采用Markdown格式便于技術文檔的傳播和閱讀??筛鶕枰M一步擴展具體代碼示例或性能分析章節。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jmm
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女