private volatile Boolean flag = false;
public void method() {
synchronized (flag) { // 看似同一把鎖
flag = !flag; // 自動裝箱:flag 指向 Boolean.TRUE 或 Boolean.FALSE
// 此時其他線程可能持有舊 Boolean 對象的鎖,導致同步失效
}
}
原因:false → Boolean.FALSE,true → Boolean.TRUE。修改變量值實際是變量指向不同的常量對象,synchronized 鎖住的是對象頭,對象變了鎖就失效。
private volatile Boolean lock1 = Boolean.FALSE;
private volatile Boolean lock2 = false; // 也是 Boolean.FALSE
public void methodA() { synchronized(lock1) { ... } }
public void methodB() { synchronized(lock2) { ... } }
原因:Boolean.FALSE 和 false 都指向常量池中同一個 Boolean.FALSE 實例。本應獨立的兩把鎖變成同一把,導致 methodA 和 methodB 錯誤串行化。
public class BooleanSyncTest {
private volatile Boolean flag = Boolean.FALSE;
public void test() {
for (int i=0; i<10; i++) {
new Thread(() -> {
synchronized (flag) {
flag = !flag;
System.out.println(Thread.currentThread().getName() + " flag=" + flag);
try { Thread.sleep((long)(Math.random()*1000)); } catch (Exception e) {}
if (!flag) System.out.println(Thread.currentThread().getName() + " 同步失效!");
flag = !flag;
}
}).start();
}
}
public static void main(String[] args) {
new BooleanSyncTest().test();
}
}
// 運行會間歇性輸出「同步失效!」
private final Object lock = new Object();private final Boolean lock = new Boolean(false);(每次 new 創建新對象)Integer、Long、String 同理private final Object lock = new Object(); 作為同步鎖volatile boolean(基本類型),同步用獨立鎖對象synchronized(包裝類變量) 模式