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

Java 多線程 Boolean 常量同步風險實測與最佳實踐指南

     編輯:Java 相關知識

核心風險點

在 synchronized 中使用 Boolean、Integer、String 等不可變包裝類/常量作為鎖,極易引發兩類隱蔽 Bug:

  1. 鎖對象悄悄替換:自動裝箱/拆箱導致變量指向不同常量實例
  2. 無關代碼共享同一把鎖:常量池機制使字面量指向同一對象

實測場景一:標誌位翻轉同步失效

private volatile Boolean running = false;
public void toggle() {
    synchronized (running) {
        running = !running; // 裝箱後 running 指向 Boolean.TRUE/FALSE
        // 其他線程可能持有舊 Boolean 對象的鎖,並發執行臨界區
    }
}

多線程並發測試會觀察到臨界區被同時進入,輸出「同步失效」。

實測場景二:獨立業務誤串行

private Boolean lockA = Boolean.FALSE;
private Boolean lockB = false; // 同一常量對象
public void taskA() { synchronized(lockA) { /* 耗時操作 */ } }
public void taskB() { synchronized(lockB) { /* 耗時操作 */ } }

本應並行的 taskA 和 taskB 因共享 Boolean.FALSE 而串行執行,性能大幅下降。

正解:專用不可變鎖對象

// 方案一:Object 鎖(推薦)
private final Object lock = new Object();
// 方案二:new 包裝類(每次 new 創建新對象)
private final Boolean lock = new Boolean(false);
// 方案三:ReentrantLock 顯式鎖
private final Lock lock = new ReentrantLock();

代碼審查檢查清單

  • [ ] 是否存在 synchronized(包裝類變量)?
  • [ ] 是否存在 synchronized(字符串字面量)?
  • [ ] 是否存在 synchronized(基本類型包裝類字段)?
  • [ ] 所有同步塊是否使用 private final Object 專用鎖?

延伸:其他不可變類同理

類型風險示例
Integer-128~127 常量池共享synchronized(count) count 為 Integer
String字面量/ intern() 共享synchronized("LOCK")
Long-128~127 常量池同 Integer
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved