happens-before 規定了對共享變數的寫入操作對其它線程的讀取操作可見,它是可見性與有序性的一套規則總結,拋開以下happens-before 規則,JMM 並不能保證一個線程對共享變量的寫,對於其它線程對該共享變量的讀取可見.
線程解鎖m 之前對變量的寫,對於接下來對m 加鎖的其它線程對該變數的讀取可見
static int x; static Object m = new Object(); new Thread(()->{ synchronized(m) { x = 10; } },"t1").start(); new Thread(()->{ synchronized(m) { System.out.println(x); } },"t2").start(); /* 运行结果: 10 */
#線程對volatile 變數的寫,對接下來其它線程對該變數的讀取可見
volatile static int x; new Thread(()->{ x = 10; },"t1").start(); new Thread(()->{ System.out.println(x); },"t2").start(); /* 运行结果: 10 */
線程start 前對變數的寫,對該線程開始後對該變數的讀取可見
static int x; x = 10; new Thread(()->{ System.out.println(x); },"t2").start(); /* 运行结果: 10 */
線程結束前對變數的寫,對其它線程得知它結束後的讀可見(比如其它線程調用t1.isAlive() 或t1.join()等待它結束)
static int x; Thread t1 = new Thread(()->{ x = 10; },"t1"); t1.start(); t1.join(); System.out.println(x); /* 运行结果: 10 */
線程t1打斷t2(interrupt)前對變數的寫,對於其他執行緒得知t2 被打斷後對變數的讀取可見(透過t2.interrupted 或t2.isInterrupted)
static int x; public static void main(String[] args) { Thread t2 = new Thread(()->{ while(true) { if(Thread.currentThread().isInterrupted()) { System.out.println(x); break; } } },"t2"); t2.start(); new Thread(()->{ sleep(1); x = 10; t2.interrupt(); },"t1").start(); while(!t2.isInterrupted()) { Thread.yield(); } System.out.println(x); } /* 运行结果: 10 */
對變數預設值(0,false,null)的寫,對其它線程對該變數的讀可見
static int a; public static void main(String[] args) { new Thread(()->{ System.out.println(a); }).start(); } /* 运行结果: 0 */
具有傳遞性,如果x hb-> y 並且y hb-> z 那麼有x hb-> z ,配合volatile 的防指令重排,有下面的例子
volatile static int x; static int y; new Thread(()->{ y = 10; x = 20; },"t1").start(); new Thread(()->{ // x=20 对 t2 可见, 同时 y=10 也对 t2 可见 System.out.println(x); },"t2").start(); /* 运行结果: 20 */
以上是java線程之Happens before規則是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!