static class IRun implements Runnable {
boolean exec = true;
public void setStop() { exec = false; }
public void run() {
int c = 0;
while (exec) { c++; } // 空循環
System.out.println("退出了循環");
}
}
主線程 sleep 1s 後調用 setStop(),32 位 JVM 正常退出,**64 位 JVM (Server VM) 永不退出**。
run() 編譯為機器碼。exec 為實例字段,無同步、無 volatile,判定**線程局部不可變**。while(true) { c++; },完全移除字段讀取。exec 寫入堆內存,編譯後代碼**永不重讀**,陷入死循環。反編譯 class 文件顯示 while(exec) 編譯為 ifeq 跳轉,**非** while(true),證明**源碼級未優化**,優化發生在 **JIT 機器碼層面**。
String s = new String() 即正常?volatile boolean exec = true; // 強制每次從主內存讀取,禁止寄存器緩存
// 或
AtomicBoolean exec = new AtomicBoolean(true);
// 或
synchronized 保護讀寫
Thread.stop() / interrupt() 等標準協作機制,而非自定義標志位。-XX:+PrintCompilation 觀察熱點編譯行為。