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

Java 線程同步核心機制深度解析

     編輯:Java 相關知識

同步問題的由來

多線程並發訪問共享數據時,若缺乏協調,極易導致數據破壞。例如兩個線程同時對同一對象的 int 字段進行遞減操作,因操作非原子性,最終結果會偏離預期。

鎖與同步的基本原理

內置鎖

每個 Java 對象天生擁有一把內置鎖(Monitor)。線程進入非靜態 synchronized 方法/塊時自動獲取該實例鎖;靜態 synchronized 則鎖定 Class 對象。鎖具有互斥性:同一時刻只能有一個線程持有,其他線程阻塞等待。

關鍵規則

  • 同步的是方法/代碼塊,而非變量或類。
  • 一個對象僅有一把鎖;同步時必須明確「在哪個對象上同步」。
  • 類可同時擁有同步與非同步方法;非同步方法不受鎖限制。
  • 線程睡眠不釋放已持有的鎖。
  • 線程可重入:同一線程可多次獲取同一把鎖。
  • 應縮小同步範圍,優先使用同步代碼塊而非整個方法。

靜態方法同步

靜態 synchronized 方法鎖定的是當前類的 Class 對象(如 MyClass.class),與實例方法鎖互不干擾。等價寫法:synchronized(MyClass.class) { ... }。

線程無法獲取鎖時的行為

線程進入該對象的等待池,直到鎖被釋放並重新獲得 CPU 時間片。阻塞關係取決於鎖對象:

  • 同一實例的非靜態同步方法互斥;不同實例則無關。
  • 同一類的靜態同步方法互斥。
  • 靜態與非靜態同步方法永不互斥(鎖對象不同)。
  • 同步代碼塊需明確指定鎖對象;同一對象上同步的線程互斥。

何時需要同步

當多線程同時讀寫可變共享數據時。非靜態字段用非靜態同步方法保護;靜態字段用靜態同步方法保護。跨層級訪問(非靜態方法用靜態字段等)屬進階場景,需謹慎設計。

線程安全類的陷阱

即使使用線程安全集合(如 Collections.synchronizedList),複合操作(先檢查 size 再 remove)仍非原子,需在業務層面再次同步。例如 NameList 類需將 add/removeFirst 方法標記 synchronized,確保「檢查-執行」原子性。

死鎖:理論與實踐

死鎖發生於兩線程循環等待對方持有的鎖。經典案例:read() 鎖 A 再鎖 B,write() 鎖 B 再鎖 A。雖觸發概率極低,但後果嚴重。預防策略:始終按固定順序獲取鎖。

總結

  1. 同步保護共享資源,核心是鎖機制。
  2. 每個對象一把鎖;靜態鎖定 Class 對象。
  3. 明確「在哪個對象上同步」是關鍵。
  4. 編寫線程安全類需識別「原子操作邊界」。
  5. 死鎖難現易亡,靠規範鎖順序預防。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved