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

Java 多線程與並發編程核心知識體系總結

     編輯:Java 程式設計入門

一、計算機系統與 JMM 基石

硬體層挑戰

  • 高速快取:CPU 從主存複製熱點數據到 L1/L2/L3 快取,運算後再回寫,解決 CPU 與主存速度差
  • 快取一致性協議(MESI 等):多核心下保證各核心快取數據一致
  • 亂序執行優化:CPU 為榨乾吞吐率,可能重排指令順序

Java 內存模型 (JMM) 核心規範

  1. 所有共享變量存儲於主內存
  2. 每條線程有私有工作內存,持有共享變量副本
  3. 線程操作變量必須在工作內存,不可直接讀寫主內存
  4. 線程間通信必須經過主內存中轉

八大內存交互操作

操作作用對象含義
lock主內存標識變量為線程獨佔
read主內存傳輸變量值到工作內存
load工作內存將 read 獲取的值放入副本
use工作內存傳遞值給執行引擎
assign工作內存執行引擎賦值給副本
store工作內存傳送副本值到主內存
write主內存將 store 獲取的值寫入主內存
unlock主內存釋放獨佔狀態

關鍵規則

  • read/load、store/write 必須成對出現
  • assign 後必須同步回主內存
  • 新變量只能在主內存誕生
  • 同一時刻僅一線程可 lock,但可重入
  • lock 會清空工作內存副本,需重新 read/load
  • unlock 前必須同步回主內存

二、volatile、原子性、可見性、有序性

volatile 兩大語義

  1. 可見性:寫入後立即刷新到主內存,讀取前強制從主內存載入
  2. 禁止指令重排序:寫屏障 + 讀屏障,保證前後操作不越界

適用場景:單寫多讀、狀態標誌、DCL 雙重檢查鎖單例模式。

三大特性對比

特性實現手段備註
原子性基本類型讀寫、synchronized、Lock、原子類長整型/雙精度在 32 位 JVM 非原子
可見性volatile、synchronized (unlock 前 flush)、finalfinal 構造器初始化完成且 this 不逸出
有序性volatile (禁止重排)、synchronized (鎖串行化)happens-before 原則是核心判斷依據

三、Happens-Before 先行發生原則

判斷操作 A 是否對操作 B 可見的偏序關係,八大規則:

  1. 程序次序:單線程內按控制流順序
  2. 管程鎖定:unlock 先於後續同鎖 lock
  3. volatile 變量:寫先於後續讀
  4. 線程啟動:start() 先於線程內任意操作
  5. 線程終止:線程內操作先於 join()/isAlive() 檢測
  6. 線程中斷:interrupt() 先於中斷檢測
  7. 對象終結:構造器結束先於 finalize()
  8. 傳遞性:A hb B, B hb C ⇒ A hb C

時間先後順序 ≠ Happens-Before;HB 是編譯器/運行時的承諾,而非物理時鐘。

四、線程實現模型與調度

三種實現模型

  • 1:1 內核線程:Java 線程直接映射 LWP(Linux/Windows JDK 默認),調度交給 OS,阻塞一個不影響其他
  • N:1 用戶線程:完全用戶態管理,切換快但無法利用多核,一個阻塞全阻塞
  • M:N 混合模型:用戶線程多對多映射內核線程,複雜度高

線程調度

  • Java 採用搶占式:時間片由 OS 分配,線程不可控制切換
  • 優先級(1-10)僅為提示,平台相關性強,不可過度依賴

五、線程六大狀態

狀態觸發條件備註
NEWnew Thread()未 start
RUNNABLEstart()包含 Ready + Running
BLOCKED等待 synchronized 鎖等待進入同步塊/方法
WAITINGwait()、join()、LockSupport.park()無超時,需顯式喚醒
TIMED_WAITINGsleep、wait(timeout)、join(timeout)超時自動返回
TERMINATEDrun() 結束正常或異常結束

六、線程安全分級與實現策略

安全分級

  • 不可變:final 基本類型、String、enum、Number 子類(除 Atomic)
  • 絕對線程安全:極少,如 CopyOnWriteArrayList
  • 相對線程安全:單操作安全,複合操作需外部同步(Vector、HashTable)
  • 線程兼容:需調用方同步
  • 線程對立:無論是否同步都不安全(System.setIn/Out)

三大實現路線

  1. 互斥同步:synchronized(JVM 內建、可重入、自動釋放)、ReentrantLock(可中斷、公平鎖、多 Condition)
  2. 非阻塞同步 (CAS):樂觀鎖,AtomicInteger 等,自旋重試直到成功
  3. 無同步方案:可重入代碼(無狀態)、ThreadLocal(線程封閉)、棧封閉

七、JVM 鎖優化演進

Mark Word 狀態機 (32 位 HotSpot)

狀態Mark Word 內容標誌位
無鎖HashCode、Age01
輕量級鎖指向棧幀 Lock Record 指針00
重量級鎖指向 ObjectMonitor 指針10
GC 標記空11
可偏向ThreadID、Epoch、Age01

四階段升級

  1. 偏向鎖:無競爭時,CAS 寫入 ThreadID,後續進出同步塊零開銷
  2. 輕量級鎖:競爭出現,CAS 將 Mark Word 指向棧幀 Lock Record,自旋等待
  3. 膨脹重量級鎖:自旋失敗/多線程競爭,轉用 OS Mutex,線程阻塞
  4. 鎖消除/粗化:JIT 編譯期優化,逃逸分析判斷無競爭則消除,連續同步塊合併

八、核心 API 精要

方法關鍵語義鎖行為
wait()釋放鎖、進入等待隊列釋放當前對象鎖
notify()/notifyAll()喚醒等待隊列線程需持有鎖,不釋放鎖
sleep()讓出 CPU、不釋放鎖保持所有鎖
join()等待目標線程終止底層用 wait() 實現
yield()提示調度器重新調度不保證讓出
interrupt()設置中斷標誌、喚醒阻塞被阻塞時拋 InterruptedException 並清除標誌

九、死鎖與避免

  • 條件:互斥、請求保持、不可剝奪、循環等待
  • 常見:雙線程互相 join、嵌套同步塊加鎖順序不一致
  • 預防:固定加鎖順序、tryLock 超時、避免長事務、使用並發容器替代手工同步
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved