多線程並發訪問共享數據時,若缺乏協調,極易導致數據破壞。例如兩個線程同時對同一對象的 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。雖觸發概率極低,但後果嚴重。預防策略:始終按固定順序獲取鎖。