java線程之Happens before規(guī)則案例詳解
正文
happens-before 規(guī)定了對(duì)共享變量的寫操作對(duì)其它線程的讀操作可見,它是可見性與有序性的一套規(guī)則總結(jié),拋開以下 happens-before 規(guī)則,JMM 并不能保證一個(gè)線程對(duì)共享變量的寫,對(duì)于其它線程對(duì)該共享變量的讀可見.
案例1
線程解鎖 m 之前對(duì)變量的寫,對(duì)于接下來對(duì) m 加鎖的其它線程對(duì)該變量的讀可見
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();
/*
運(yùn)行結(jié)果:
10
*/
案例2
線程對(duì) volatile 變量的寫,對(duì)接下來其它線程對(duì)該變量的讀可見
volatile static int x;
new Thread(()->{
x = 10;
},"t1").start();
new Thread(()->{
System.out.println(x);
},"t2").start();
/*
運(yùn)行結(jié)果:
10
*/
案例3
線程 start 前對(duì)變量的寫,對(duì)該線程開始后對(duì)該變量的讀可見
static int x;
x = 10;
new Thread(()->{
System.out.println(x);
},"t2").start();
/*
運(yùn)行結(jié)果:
10
*/
案例4
線程結(jié)束前對(duì)變量的寫,對(duì)其它線程得知它結(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);
/*
運(yùn)行結(jié)果:
10
*/
案例5
線程 t1 打斷 t2(interrupt)前對(duì)變量的寫,對(duì)于其他線程得知 t2 被打斷后對(duì)變量的讀可見(通過 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);
}
/*
運(yùn)行結(jié)果:
10
*/
案例6
對(duì)變量默認(rèn)值(0,false,null)的寫,對(duì)其它線程對(duì)該變量的讀可見
static int a;
public static void main(String[] args) {
new Thread(()->{
System.out.println(a);
}).start();
}
/*
運(yùn)行結(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 對(duì) t2 可見, 同時(shí) y=10 也對(duì) t2 可見
System.out.println(x);
},"t2").start();
/*
運(yùn)行結(jié)果:
20
*/以上就是java線程之Happens-before規(guī)則的詳細(xì)內(nèi)容,更多關(guān)于線程Happens-before規(guī)則的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
IDEA2023常用配置指南(JDK/系統(tǒng)設(shè)置等常用配置)
idea很強(qiáng)大,但是初次安裝默認(rèn)的有很多設(shè)置并不是滿足我們開發(fā)的需要,下面這篇文章主要給大家介紹了關(guān)于IDEA2023常用配置(JDK/系統(tǒng)設(shè)置等常用配置)的相關(guān)資料,需要的朋友可以參考下2023-12-12
Java?-jar參數(shù)設(shè)置小結(jié)
本文主要介紹了Java?-jar參數(shù)設(shè)置小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解
這篇文章主要介紹了java解析xml的4種方式的優(yōu)缺點(diǎn)對(duì)比及實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07
修改idea運(yùn)行內(nèi)存大小的方法總結(jié)
在開發(fā)過程中,總會(huì)遇到idea運(yùn)行內(nèi)存不足,所以本文小編給大家介紹了修改idea運(yùn)行內(nèi)存大小的兩種方法,文中通過圖文給大家講解的非常詳細(xì),需要的朋友可以參考下2023-12-12
Java編程通過list接口實(shí)現(xiàn)數(shù)據(jù)的增刪改查代碼示例
這篇文章是介紹Java編程基礎(chǔ)方面的內(nèi)容,涉及l(fā)ist接口的操作,通過list接口實(shí)現(xiàn)對(duì)數(shù)據(jù)的增刪改查的相關(guān)代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
Java實(shí)現(xiàn)學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)學(xué)生管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

