關於系統重排序對多執行緒的影響案例復現
阿新 • • 發佈:2022-01-16
最近一直在看《Java 併發程式設計的藝術》這本書,有一說一,書是真的不錯。
但是在 P29 講到重排序對多執行緒的影響這個小結時,例項程式碼邏輯上確實說的過去,但是我在 IDEA 一直無法復現,沒有重排序的現象出現。一切以事實說話,到底在多執行緒中有沒有重排序?或者直接說作業系統裡面有沒有對指令重排序。於是我找到了一個多執行緒新的案例這是原地址
public class ThreadReorderTest { /** 設定初始值 */ static class State { int a = 0; int b = 0; int c = 0; } public static void main(String[] args) { for (int i = 0; i < 1000_000; i++) { final State state = new State(); // a = 0, b = 0, c = 0 // Write values 寫入資料程序 new Thread(() -> { state.a = 1; // a = 1, b = 0, c = 0 state.b = 1; // a = 1, b = 1, c = 0 state.c = state.a + 1; // a = 1, b = 1, c = 2 }).start(); // Read values - this should never happen, right? 讀入資料程序,重排序真的會發生嗎 new Thread(() -> { // copy in reverse order so if we see some invalid state we know this is caused by reordering and not by a race condition in reads/writes // we don't know if the reordered statements are the writes or reads (we will se it is writes later) int tmpC = state.c; int tmpB = state.b; int tmpA = state.a; if (tmpB == 1 && tmpA == 0) { System.out.println("Hey wtf!! b == 1 && a == 0"); } if (tmpC == 2 && tmpB == 0) { System.out.println("Hey wtf!! c == 2 && b == 0"); } if (tmpC == 2 && tmpA == 0) { System.out.println("Hey wtf!! c == 2 && a == 0"); } }).start(); } System.out.println("done"); } }
運行了大概十幾次,終於出現了重排結果:Hey wtf!! c == 2 && b == 0
如果沒有重排,按照兩個執行緒的順序,不會出現任何 Hey wtf!! 字樣的列印結果。說明發生了如下圖的重排