Java內存模型(JMM)的核心概念與線程安全詳細解析

Java內存模型(jmm)是線程編程的基礎,其核心在于主內存與工作內存的劃分及三大特性(原子性、可見性、有序性)。1.主內存存儲變量,線程通過工作內存操作變量副本,通信需同步機制避免可見性問題;2.線程安全依賴原子性(如synchronized或atomicinteger保障)、可見性(volatile確保讀寫主內存)、有序性(volatile和synchronized禁止重排序);3.happens-before規則定義操作間可見關系,包括程序順序、鎖、volatile變量、線程啟動與終止等規則;4.開發中需注意非原子操作、volatile合理使用、減少共享變量等細節,以寫出可靠的并發程序。

Java內存模型(JMM)的核心概念與線程安全詳細解析

Java內存模型(JMM)是理解多線程編程、實現線程安全的基礎。很多人寫并發程序的時候,可能只關心synchronized或volatile這些關鍵字,但如果不了解JMM背后的機制,就容易寫出看似正確實則有問題的代碼。

Java內存模型(JMM)的核心概念與線程安全詳細解析

下面我們就從幾個關鍵點來聊聊JMM的核心概念和線程安全的一些細節。

Java內存模型(JMM)的核心概念與線程安全詳細解析


主內存與工作內存:線程之間如何通信

在JMM中,所有變量都存儲在主內存中,每個線程有自己的“工作內存”,里面保存了該線程使用到變量的副本。線程對變量的所有操作(讀取、賦值等)都是在自己的工作內存中進行的,不能直接讀寫主內存中的變量。

立即學習Java免費學習筆記(深入)”;

舉個例子,假設兩個線程同時操作一個int變量count

Java內存模型(JMM)的核心概念與線程安全詳細解析

  • 線程A修改了count的值,這個修改一開始只是存在它自己的工作內存里。
  • 如果線程B想看到這個變化,必須通過某些機制把線程A的更新同步回主內存,然后線程B再從主內存讀取。

這種機制如果不處理好,就會出現“可見性”問題,比如線程B看不到線程A改過的值。


原子性、可見性、有序性:線程安全的三大基礎

要保障線程安全,通常需要考慮三個方面:原子性、可見性和有序性。

原子性

簡單來說就是某個操作要么全部執行成功,要么完全不執行。例如i++看起來是一條語句,實際上包含三個步驟:

  • 讀取i的值
  • 加1
  • 寫回新值

這三個步驟不是原子操作,多個線程同時執行的話可能會導致結果錯誤。解決辦法可以用synchronized或者AtomicInteger等原子類。

可見性

前面提到過,線程之間的變量修改不一定能及時被其他線程看到。volatile關鍵字可以保證變量的可見性,每次讀取都會去主內存拿最新值,每次寫完也會立即刷新回主內存。

有序性

編譯器或處理器為了優化性能,可能會重排指令順序。雖然重排不會影響單線程的結果,但在多線程環境下可能導致問題。volatile和synchronized都能禁止某些重排序,從而保證程序的有序性。


happens-before規則:理解JMM的關鍵

happens-before是JMM中最核心的概念之一,它定義了兩個操作之間的可見關系。如果操作A happens-before 操作B,那么A的結果對B是可見的。

常見的happens-before規則包括:

  • 程序順序規則:同一個線程中的每個操作,都按代碼順序發生。
  • 監視器鎖規則:對同一個鎖的解鎖操作 happens-before 后續對這個鎖的加鎖操作。
  • volatile變量規則:對volatile變量的寫操作 happens-before 后續對該變量的讀操作。
  • 線程啟動規則:Thread.start() happens-before 線程中的任何操作。
  • 線程終止規則:線程中的所有操作 happens-before 其他線程檢測到該線程已經結束。

掌握這些規則有助于我們判斷哪些操作之間有可見性保證,從而避免錯誤的并發邏輯。


實際開發中需要注意的幾個細節

  • 不要依賴“看似正確”的代碼:比如用雙重檢查創建單例時,如果沒有給實例加上volatile,可能會因為指令重排導致返回未構造完成的對象。
  • 注意long和double的非原子性:在32位jvm上,對64位的long和double變量的讀寫可能不是原子的,需要用volatile修飾來保證原子性。
  • 合理使用volatile:volatile適用于狀態標志、一次初始化等場景,但如果涉及復合操作,還是得用鎖或原子類。
  • 盡量減少共享變量:最安全的并發方式是沒有共享數據,比如使用ThreadLocal來隔離線程間的數據訪問

基本上就這些內容。Java內存模型雖然抽象,但它決定了我們在多線程環境中看到的行為是否符合預期。掌握這些基本概念,才能寫出真正可靠的并發程序。

? 版權聲明
THE END
喜歡就支持一下吧
點贊6 分享