java線程之Happens before規(guī)則案例詳解
正文
happens-before 規(guī)定了對共享變量的寫操作對其它線程的讀操作可見,它是可見性與有序性的一套規(guī)則總結(jié),拋開以下 happens-before 規(guī)則,JMM 并不能保證一個線程對共享變量的寫,對于其它線程對該共享變量的讀可見.
案例1
線程解鎖 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(); /* 運行結(jié)果: 10 */
案例2
線程對 volatile 變量的寫,對接下來其它線程對該變量的讀可見
volatile static int x; new Thread(()->{ x = 10; },"t1").start(); new Thread(()->{ System.out.println(x); },"t2").start(); /* 運行結(jié)果: 10 */
案例3
線程 start 前對變量的寫,對該線程開始后對該變量的讀可見
static int x; x = 10; new Thread(()->{ System.out.println(x); },"t2").start(); /* 運行結(jié)果: 10 */
案例4
線程結(jié)束前對變量的寫,對其它線程得知它結(jié)束后的讀可見(比如其它線程調(diào)用 t1.isAlive() 或 t1.join()等待 它結(jié)束)
static int x; Thread t1 = new Thread(()->{ x = 10; },"t1"); t1.start(); t1.join(); System.out.println(x); /* 運行結(jié)果: 10 */
案例5
線程 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); } /* 運行結(jié)果: 10 */
案例6
對變量默認(rèn)值(0,false,null)的寫,對其它線程對該變量的讀可見
static int a; public static void main(String[] args) { new Thread(()->{ System.out.println(a); }).start(); } /* 運行結(jié)果: 0 */
案例7
具有傳遞性,如果 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(); /* 運行結(jié)果: 20 */
以上就是java線程之Happens-before規(guī)則的詳細(xì)內(nèi)容,更多關(guān)于線程Happens-before規(guī)則的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot多文件上傳實現(xiàn)使用postman測試多文件上傳接口
這篇文章主要介紹了springboot多文件上傳實現(xiàn)使用postman測試多文件上傳接口,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08java動態(tài)代理和cglib動態(tài)代理示例分享
這篇文章主要介紹了java動態(tài)代理和cglib動態(tài)代理示例,JDK1.3之后,Java提供了動態(tài)代理的技術(shù),允許開發(fā)者在運行期間創(chuàng)建接口的代理實例,下面我們使用示例學(xué)習(xí)一下2014-03-03springboot webflux 過濾器(使用RouterFunction實現(xiàn))
這篇文章主要介紹了springboot webflux 過濾器(使用RouterFunction實現(xiàn)),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03聊聊@value注解和@ConfigurationProperties注解的使用
這篇文章主要介紹了@value注解和@ConfigurationProperties注解的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09springboot用戶數(shù)據(jù)修改的詳細(xì)實現(xiàn)
用戶管理功能作為所有的系統(tǒng)是必不可少的一部分,下面這篇文章主要給大家介紹了關(guān)于springboot用戶數(shù)據(jù)修改的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04