<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java內存模型(JMM)一文透徹理解

      JMM核心內容概覽與重要程度評級

      在學習JMM前,我們先了解其核心內容體系及重要程度:

      內容模塊 重要程度 說明
      1. JMM基礎概念 ???? 理解JMM的出發點和基本架構
      - 硬件基礎與并發挑戰 ???? 了解JMM存在的必要性
      - 主內存與工作內存 ???? JMM的核心抽象概念
      2. 內存間交互操作 ??? JMM的基礎操作定義
      3. volatile關鍵字 ????? 最常用的同步機制,必須深入掌握
      4. synchronized內存語義 ????? 理解鎖的內存效應
      5. happens-before規則 ????? JMM的理論核心,解決可見性問題的關鍵
      6. 原子性、可見性、有序性 ????? 并發編程的三大核心問題
      7. 安全發布模式 ???? 實際開發中的常用技巧
      8. final字段語義 ??? 特殊但重要的內存語義
      9. 雙重檢查鎖定問題 ???? 經典問題的分析與解決方案
      10. JMM底層實現 ??? 理解原理,優化性能

      接下來,我們將按照重要程度,逐一深入講解各個模塊。

      1. JMM是什么?為什么需要JMM?

      1.1 JMM的定義與作用

      Java內存模型(Java Memory Model, JMM) 是Java虛擬機規范中定義的一種抽象規范,用于屏蔽各種硬件和操作系統的內存訪問差異,實現Java程序在各種平臺下都能達到一致的內存訪問效果。

      JMM的核心作用

      1. 定義規則:規定多線程環境下變量的訪問方式
      2. 提供保證:確保在不同平臺上內存訪問行為的一致性
      3. 允許優化:在保證正確性的前提下允許編譯器和處理器進行優化

      1.2 為什么需要JMM:硬件層面的挑戰

      現代計算機系統的多層次存儲架構導致了并發編程的三大核心問題:

      public class ConcurrencyProblems {
          private static boolean ready = false;
          private static int number = 0;
          
          public static void main(String[] args) {
              // 線程1:數據準備
              Thread writer = new Thread(() -> {
                  number = 42;    // 操作1:可能被重排序到操作2之后
                  ready = true;   // 操作2:可能先執行
              });
              
              // 線程2:數據處理
              Thread reader = new Thread(() -> {
                  while (!ready) {
                      // 等待ready變為true
                      Thread.yield();
                  }
                  // 可能輸出0而不是42!
                  System.out.println("Number: " + number);
              });
              
              writer.start();
              reader.start();
          }
      }
      

      問題根源

      1. CPU緩存一致性:多核CPU各有緩存,數據更新不同步
      2. 指令重排序:編譯器和處理器為優化性能重新排序指令
      3. 內存可見性:一個線程的修改對其他線程不可見

      2. JMM的核心架構:主內存與工作內存

      JMM通過抽象的內存模型解決上述問題:

      graph TB subgraph "JMM內存模型" MM[主內存 Main Memory<br>共享變量存儲區域] subgraph "線程1" WM1[工作內存<br>主內存變量副本] TE1[執行引擎] WM1 --> TE1 TE1 --> WM1 end subgraph "線程2" WM2[工作內存<br>主內存變量副本] TE2[執行引擎] WM2 --> TE2 TE2 --> WM2 end MM -- read/load --> WM1 WM1 -- store/write --> MM MM -- read/load --> WM2 WM2 -- store/write --> MM end subgraph "物理硬件對應關系" CPU1[CPU Core 1] --> CACHE1[緩存 L1/L2] CPU2[CPU Core 2] --> CACHE2[緩存 L1/L2] CACHE1 --> LLC[共享緩存 L3] CACHE2 --> LLC LLC --> RAM[主內存 RAM] end

      工作內存與主內存的交互通過8種原子操作完成

      public class MemoryOperations {
          private int sharedValue = 0;
          
          public void operationExample() {
              // 1. read: 從主內存讀取變量到傳輸通道
              // 2. load: 將read得到的值放入工作內存的變量副本
              // 相當于: int temp = sharedValue; (但這是高級語言表示)
              
              // 3. use: 將工作內存中的變量傳遞給執行引擎
              int result = sharedValue * 2;
              
              // 4. assign: 將執行引擎的結果賦給工作內存中的變量
              sharedValue = result + 1;
              
              // 5. store: 將工作內存中的變量值傳輸到主內存的傳輸通道
              // 6. write: 將store獲取的值放入主內存的變量
              
              // 7. lock: 將主內存變量標記為線程獨占狀態
              // 8. unlock: 釋放鎖定的變量
          }
      }
      

      3. ????? volatile關鍵字深度解析

      3.1 volatile的語義與保證

      volatile是JVM提供的最輕量級的同步機制,提供兩大保證:

      1. 可見性保證:對volatile變量的寫操作立即對其他線程可見
      2. 禁止重排序:阻止編譯器和處理器對volatile操作進行重排序
      public class VolatileExample {
          private volatile boolean flag = false;
          private int value = 0;
          
          public void writer() {
              value = 42;      // 普通寫操作
              // StoreStore內存屏障:禁止上面的普通寫與下面的volatile寫重排序
              flag = true;     // volatile寫操作
              // StoreLoad內存屏障:確保volatile寫立即對其他處理器可見
          }
          
          public void reader() {
              // LoadLoad內存屏障:確保volatile讀之前的所有讀操作已完成
              if (flag) {      // volatile讀操作
                  // LoadStore內存屏障:確保volatile讀之后的寫操作不會重排序到讀之前
                  System.out.println(value); // 保證看到value = 42
              }
          }
      }
      

      3.2 volatile的實現原理

      在硬件層面,volatile通過內存屏障指令實現:

      public class VolatileBarrier {
          private volatile int value;
          
          public void setValue(int newValue) {
              this.value = newValue;
              // 對應x86匯編代碼:
              // mov    %eax,0x10(%rsi)   ; 將newValue存入value的內存地址
              // lock addl $0x0,(%rsp)    ; StoreLoad內存屏障(mfence指令)
          }
          
          public int getValue() {
              // volatile讀在x86上不需要特殊指令
              // 因為x86的內存模型已經保證了可見性(TSO模型)
              return value;
          }
      }
      

      內存屏障類型

      • LoadLoad屏障:禁止讀操作重排序
      • StoreStore屏障:禁止寫操作重排序
      • LoadStore屏障:禁止讀與寫操作重排序
      • StoreLoad屏障:禁止寫與讀操作重排序(最重量級)

      3.3 volatile的使用場景與限制

      適用場景

      1. 狀態標志位
      2. 一次性安全發布
      3. 獨立觀察(independent observation)
      4. 開銷較低的讀-寫鎖策略

      不適用場景

      • 復合操作(如i++)
      • 依賴于當前值的操作(如value = value + 1)
      public class VolatileUsage {
          // 場景1:狀態標志位
          private volatile boolean shutdownRequested;
          
          public void shutdown() {
              shutdownRequested = true;
          }
          
          public void doWork() {
              while (!shutdownRequested) {
                  // 執行工作任務
              }
          }
          
          // 場景2:一次性安全發布
          private volatile Resource resource;
          
          public Resource getResource() {
              if (resource == null) {
                  synchronized(this) {
                      if (resource == null) {
                          resource = new Resource(); // 安全發布
                      }
                  }
              }
              return resource;
          }
      }
      

      4. ????? synchronized的內存語義

      synchronized不僅提供互斥執行,還提供重要的內存語義:

      public class SynchronizedMemory {
          private int counter = 0;
          private final Object lock = new Object();
          
          public void increment() {
              synchronized(lock) { 
                  // monitorenter指令:
                  // 1. 清空工作內存
                  // 2. 從主內存重新加載所有共享變量
                  counter++;
                  // 臨界區內的操作不會被重排序到臨界區外
              } 
              // monitorexit指令:
              // 1. 將工作內存中的修改刷新到主內存
              // 2. 釋放鎖
          }
          
          public int getCounter() {
              synchronized(lock) {
                  // 獲取鎖會強制從主內存重新讀取變量
                  return counter;
              }
          }
      }
      

      synchronized的內存語義

      1. 進入同步塊:清空工作內存,從主內存重新加載變量
      2. 退出同步塊:將工作內存中的修改刷新到主內存
      3. 互斥執行:確保同一時刻只有一個線程執行臨界區代碼

      5. ????? happens-before規則

      happens-before是JMM的理論核心,定義了操作之間的可見性關系。

      5.1 happens-before規則詳解

      public class HappensBeforeExample {
          private int x = 0;
          private volatile boolean v = false;
          private int y = 0;
          private final Object lock = new Object();
          
          public void demo() {
              // 規則1:程序次序規則
              x = 1;          // 操作A
              v = true;       // 操作B:A happens-before B
              
              // 規則2:volatile變量規則
              if (v) {        // 操作C:B happens-before C
                  y = x;      // 操作D:C happens-before D
              }
              
              // 規則3:傳遞性規則
              // A happens-before B, B happens-before C, C happens-before D
              // 因此 A happens-before D
              
              // 規則4:管程鎖定規則
              synchronized(lock) { // 加鎖E
                  x = 2;          // 操作F:E happens-before F
              } // 解鎖G:F happens-before G
              
              // 規則5:線程啟動規則
              Thread t = new Thread(() -> {
                  System.out.println(x); // 看到x=2
              });
              t.start(); // start() happens-before 線程中的所有操作
              
              // 規則6:線程終止規則
              try {
                  t.join(); // 線程中的所有操作 happens-before join()返回
              } catch (InterruptedException e) {
                  Thread.currentThread().interrupt();
              }
              
              // 規則7:對象終結規則
              // 對象的構造函數執行結束 happens-before finalize()方法開始
          }
      }
      

      5.2 happens-before的數學基礎

      happens-before關系是一個偏序關系,具有:

      • 自反性:A happens-before A
      • 反對稱性:如果A happens-before B且B happens-before A,則A=B
      • 傳遞性:如果A happens-before B且B happens-before C,則A happens-before C

      6. ????? 原子性、可見性、有序性

      這是并發編程的三大核心問題,JMM為每個問題提供了解決方案。

      6.1 原子性(Atomicity)

      原子性是指一個操作不可中斷,要么全部執行成功,要么完全不執行。

      public class AtomicityExample {
          private int basicType = 0; // 基本類型訪問是原子的
          private long longValue = 0L; // long和double可能非原子(但現代JVM通常保證原子性)
          private volatile boolean flag = false; // volatile保證單個讀/寫的原子性
          
          // 復合操作不是原子的
          public void nonAtomicIncrement() {
              basicType++; // 不是原子操作!分解為read-modify-write三步
          }
          
          // 保證原子性的方式
          private final AtomicInteger atomicInt = new AtomicInteger(0);
          private final Object lock = new Object();
          private int synchronizedValue = 0;
          
          public void atomicOperations() {
              // 方式1:使用原子類
              atomicInt.incrementAndGet(); // 原子操作
              
              // 方式2:使用同步
              synchronized(lock) {
                  synchronizedValue++; // 原子操作
              }
              
              // 方式3:使用volatile變量(僅適用于特定場景)
              flag = true; // 原子操作
          }
      }
      

      6.2 可見性(Visibility)

      可見性是指當一個線程修改了共享變量的值,其他線程能夠立即得知這個修改。

      public class VisibilityExample {
          private int noVisibility = 0; // 無可見性保證
          private volatile boolean hasVisibility = false; // volatile保證可見性
          private int synchronizedValue = 0; // synchronized保證可見性
          private final Object lock = new Object();
          
          public void demonstrate() {
              // 線程1:修改數據
              new Thread(() -> {
                  noVisibility = 42;
                  hasVisibility = true;
                  synchronized(lock) {
                      synchronizedValue = 100;
                  }
              }).start();
              
              // 線程2:讀取數據
              new Thread(() -> {
                  // 可能看不到noVisibility的更新
                  while (!hasVisibility) {
                      // 等待hasVisibility變為true
                  }
                  // 保證看到noVisibility = 42(因為volatile寫happens-before volatile讀)
                  
                  synchronized(lock) {
                      // 保證看到synchronizedValue = 100
                  }
              }).start();
          }
      }
      

      6.3 有序性(Ordering)

      有序性是指程序執行的順序按照代碼的先后順序執行。

      public class OrderingExample {
          private int x = 0;
          private int y = 0;
          private volatile boolean ready = false;
          
          public void orderingDemo() {
              // 線程1:可能被重排序
              new Thread(() -> {
                  x = 1;      // 操作1
                  y = 2;      // 操作2
                  ready = true; // 操作3:volatile寫,阻止重排序
              }).start();
              
              // 線程2
              new Thread(() -> {
                  while (!ready) {
                      // 等待
                  }
                  // 由于volatile的語義,這里保證看到x=1, y=2
                  // 不會出現y=2但x=0的情況
              }).start();
          }
      }
      

      7. ???? 安全發布模式

      安全地發布對象是并發編程中的常見需求,JMM提供了多種模式。

      public class SafePublication {
          // 方式1:靜態初始化器(最安全)
          private static final Resource staticResource = new Resource();
          
          // 方式2:volatile字段
          private volatile Resource volatileResource;
          
          public void initVolatileResource() {
              volatileResource = new Resource(); // 安全發布
          }
          
          // 方式3:final字段
          private final Resource finalResource;
          
          public SafePublication() {
              this.finalResource = new Resource(); // 安全發布
          }
          
          // 方式4:正常鎖保護
          private Resource guardedResource;
          private final Object lock = new Object();
          
          public void initGuardedResource() {
              synchronized(lock) {
                  if (guardedResource == null) {
                      guardedResource = new Resource(); // 安全發布
                  }
              }
          }
          
          // 方式5:線程安全容器
          private final Map<String, Resource> safeMap 
              = Collections.synchronizedMap(new HashMap<>());
          private final ConcurrentMap<String, Resource> concurrentMap 
              = new ConcurrentHashMap<>();
          
          public void addToSafeMap(String key) {
              safeMap.put(key, new Resource()); // 安全發布
          }
      }
      

      8. ???? 雙重檢查鎖定(DCL)問題與解決方案

      雙重檢查鎖定是一個經典的并發模式,但存在陷阱。

      8.1 錯誤的DCL實現

      public class BrokenDCL {
          private static Resource resource; // 沒有volatile!
          
          public static Resource getInstance() {
              if (resource == null) {                 // 第一次檢查(無鎖)
                  synchronized(BrokenDCL.class) {     // 加鎖
                      if (resource == null) {         // 第二次檢查(有鎖)
                          resource = new Resource();  // 問題所在!
                          // 可能發生的重排序:
                          // 1. 分配內存空間
                          // 2. 將引用指向內存空間(此時resource != null)
                          // 3. 初始化對象(還未執行)
                          // 其他線程可能拿到未完全初始化的對象!
                      }
                  }
              }
              return resource;
          }
      }
      

      8.2 正確的DCL實現

      public class CorrectDCL {
          // 使用volatile禁止重排序
          private static volatile CorrectDCL instance;
          
          private final int value;
          private final String name;
          
          private CorrectDCL() {
              this.value = 42;     // 初始化final字段
              this.name = "DCL";   // 初始化普通字段
              // 構造函數執行
          }
          
          public static CorrectDCL getInstance() {
              if (instance == null) {                     // 第一次檢查(無鎖)
                  synchronized(CorrectDCL.class) {        // 加鎖
                      if (instance == null) {             // 第二次檢查(有鎖)
                          instance = new CorrectDCL();    // 安全發布
                          // volatile寫插入內存屏障,確保:
                          // 1. 所有初始化操作完成
                          // 2. 初始化結果對其他線程立即可見
                      }
                  }
              }
              return instance;
          }
      }
      

      9. ??? final字段的內存語義

      final字段在并發編程中有特殊的內存語義,提供了安全初始化的保證。

      public class FinalFieldExample {
          private final int finalValue; // final字段
          private int normalValue;      // 普通字段
          private volatile boolean ready = false;
          
          public FinalFieldExample() {
              normalValue = 1;        // 普通字段寫入(可能被重排序)
              finalValue = 42;        // final字段寫入
              // JMM在此隱式插入StoreStore內存屏障
              // 確保final字段的初始化不會被重排序到構造函數之外
              
              ready = true;           // volatile寫
          }
          
          public static void reader() {
              FinalFieldExample obj = new FinalFieldExample();
              
              // 保證看到finalValue的正確值(42)
              // 即使沒有同步,也能看到正確初始化的final字段
              int r1 = obj.finalValue;
              
              // 可能看到normalValue的默認值(0)而不是1
              // 因為沒有同步保證
              int r2 = obj.normalValue;
              
              // 但如果通過volatile讀看到ready=true
              // 那么也能保證看到所有字段的正確初始化值
              if (obj.ready) {
                  // 保證看到finalValue=42和normalValue=1
              }
          }
      }
      

      10. JMM在開發中的實際應用

      10.1 性能優化建議

      1. 減少同步范圍:只在必要時使用同步
      2. 使用volatile代替鎖:當只需要可見性保證時
      3. 使用線程局部變量:避免共享,消除同步
      4. 使用并發容器:代替手動同步的容器

      10.2 常見陷阱與避免方法

      public class CommonConcurrencyMistakes {
          // 陷阱1:認為volatile保證原子性
          private volatile int count = 0;
          
          public void unsafeIncrement() {
              count++; // 不是原子操作!
          }
          
          // 解決方案:使用原子類或同步
          private final AtomicInteger safeCount = new AtomicInteger(0);
          private int synchronizedCount = 0;
          private final Object lock = new Object();
          
          public void safeIncrement() {
              safeCount.incrementAndGet(); // 方式1:原子類
              
              synchronized(lock) {         // 方式2:同步
                  synchronizedCount++;
              }
          }
          
          // 陷阱2:誤用雙重檢查鎖定
          // 解決方案:使用volatile修飾實例變量
          
          // 陷阱3:依賴線程優先級
          // 解決方案:不要依賴線程優先級進行正確性設計
          
          // 陷阱4:在構造函數中啟動線程
          public class ProblematicConstructor {
              public ProblematicConstructor() {
                  new Thread(() -> {
                      // 可能訪問未完全初始化的對象
                  }).start();
              }
          }
      }
      

      總結

      Java內存模型是Java并發編程的基石,它通過定義一系列規則和happens-before關系,在多線程環境中提供了內存可見性、原子性和有序性的保證。

      關鍵要點

      1. 理解happens-before規則:這是理解線程間操作可見性的核心
      2. 正確使用volatile:了解其適用場景和限制
      3. 掌握安全發布模式:確保對象在線程間安全共享
      4. 避免常見陷阱:識別并避免常見的并發編程錯誤

      JMM既是一個規范也是一個工具,正確理解和使用JMM可以幫助我們編寫出既正確又高效的多線程程序。在實際開發中,應該優先使用java.util.concurrent包提供的高級并發工具,它們在大多數情況下都能提供更好的性能和更簡單的編程模型。

      posted @ 2025-11-03 11:12  佛祖讓我來巡山  閱讀(150)  評論(0)    收藏  舉報

      佛祖讓我來巡山博客站 - 創建于 2018-08-15

      開發工程師個人站,內容主要是網站開發方面的技術文章,大部分來自學習或工作,部分來源于網絡,希望對大家有所幫助。

      Bootstrap中文網

      主站蜘蛛池模板: 成年女人黄小视频| 久热这里只国产精品视频| 综合色久七七综合尤物| 免费观看国产女人高潮视频| 国产老熟女无套内射不卡| 榆社县| 亚欧成人精品一区二区乱| 亚洲欧洲日韩国内高清| 在线中文一区字幕对白| 老太脱裤子让老头玩xxxxx| 国内精品无码一区二区三区| 野外做受三级视频| 亚洲精品一区二区麻豆| 国产无码高清视频不卡| 亚洲色欲色欲www在线看| 亚洲少妇一区二区三区老| 国产高潮又爽又刺激的视频| 国产无遮挡真人免费视频| 久久国产成人午夜av影院| 人妻少妇精品视频三区二区| av午夜久久蜜桃传媒软件| 在线精品自拍亚洲第一区| 黑人大战中国av女叫惨了| 久久精品国产福利亚洲av| 国产不卡一区二区精品| 伊人成伊人成综合网222| 久久亚洲精品国产精品| 亚洲中文字幕在线无码一区二区| 国产a在视频线精品视频下载 | 丰满无码人妻热妇无码区| 亚洲VA欧美VA国产综合| 亚洲 日韩 国产 制服 在线| 久久精品国产亚洲精品| 天天综合色天天综合色h| 久热这里只有精品12| 潮喷失禁大喷水av无码| 黔江区| 一本精品99久久精品77| 亚洲a人片在线观看网址| 亚洲乱码中文字幕小综合| 色国产视频|