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

Java 並發編程核心:對象共享與可見性、發布逸出、線程封閉與不可變模式深度解析

     編輯:Java 綜合教學

Java 並發編程核心:對象共享機制深度解析

在多線程環境下,對象如何安全共享是並發編程的核心課題。本文系統梳理可見性、發布與逸出、線程封閉、不可變對象及安全發布模式,構建完整知識體系。

一、可見性

缺乏同步時,編譯器、運行時可能對操作重排序,導致線程讀取到失效數據。

1. 失效數據

線程讀取共享變量時,可能看到舊值,而非其他線程最新寫入的值。

2. 非原子操作

Java 內存模型保證基本類型讀寫原子性,但 非 volatile 的 long/double (64位) 允許拆分為兩次 32 位操作。多線程並發讀寫時,可能讀到「高 32 位來自線程 A,低 32 位來自線程 B」的混合值。解決:聲明 volatile 或加鎖保護。

3. 加鎖與可見性

鎖不僅提供互斥,還建立 happens-before 關係:解鎖 happens-before 後續加鎖。所有訪問共享變量的線程必須在同一把鎖上同步,才能保證可見性。

4. volatile 變量

  • 禁止指令重排序,保證讀寫有序性
  • 不缓存寄存器,直接讀寫主內存,保證可見性
  • 輕量級同步機制,不引起線程阻塞
  • 適用場景:寫入不依賴當前值、不參與不變性條件、無需加鎖
  • 典型用法:狀態標誌位控制循環退出

對比:鎖 = 可見性 + 原子性;volatile = 僅可見性

二、發布與逸出

發布:使對象在作用域外可見(如存入 public static 字段)。
逸出:不該發布的對象被發布(如構造過程中 this 引用外洩)。

構造過程中的 this 逸出風險

  • 構造器中啟動線程(顯式傳遞 this 或內部類隱式持有)
  • 構造器中調用可覆寫方法(子類可能訪問未初始化完成的字段)
  • 最佳實踐:構造器僅初始化,提供單獨 start()/initialize() 啟動線程

三、線程封閉

不共享數據,自然線程安全。三種實現層次:

1. Ad-hoc 線程封閉

靠程序員自覺維護,脆弱。適用於單線程子系統(如 Swing 事件分發線程、請求處理線程)。

2. 棧封閉

局部變量天然封閉在線程棧中。將非線程安全對象作為局部變量使用,即可實現線程安全。

3. ThreadLocal

為每個線程提供獨立副本。get() 返回當前線程最近 set() 的值。常用於:資料庫連接持有、請求上下文傳遞、格式化器復用。
警示:類似全局變量,降低代碼復用性,引入隱式耦合,謹慎使用。

四、不可變對象

創建後狀態不可修改,天然線程安全。滿足三條件:

  1. 創建後狀態不可修改
  2. 所有域均為 final
  3. 構造過程中 this 未逸出(正確構造)

final 域語義

  • 確保初始化安全性:正確構造的 final 域,無需同步即可安全發布
  • 若 final 引用可變對象,被引用對象內部狀態仍可修改
  • 最佳實踐:除非必須可變,否則所有域聲明 private final

利用不可變對象消除競爭

將多個相關變量封裝為一個不可變對象,更新時創建新實例。讀取線程始終看到一致狀態,無需加鎖。

五、安全發布

發布對象時,必須確保引用與狀態同時對其他線程可見。

安全發布模式

  1. 靜態初始化器中初始化(JVM 保證類初始化同步性)
  2. 存入 volatile 域或 AtomicReference
  3. 存入正確構造對象的 final 域
  4. 存入由鎖保護的域中

線程安全容器的發布保證

  • Hashtable/ConcurrentMap/SynchronizedMap:put 操作安全發布鍵值
  • Vector/CopyOnWriteArrayList/SynchronizedList:add 操作安全發布元素
  • BlockingQueue/ConcurrentLinkedQueue:offer 操作安全發布元素

對象發布策略選擇

對象類型發布要求
不可變對象任意方式發布均安全
事實不可變對象必須安全發布
可變對象安全發布 + 線程安全或鎖保護

安全共享對象四大策略

  1. 線程封閉:單線程擁有、修改
  2. 只讀共享:不可變/事實不可變對象,無需同步並發讀
  3. 線程安全共享:對象內部實現同步(如 ConcurrentHashMap)
  4. 保護對象:持有特定鎖才能訪問(如同步包裝器、監視器模式)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved