Java并發(fā)volatile可見性的驗(yàn)證實(shí)現(xiàn)
普通讀 無法及時(shí)獲得 主內(nèi)存變量
public class volatileTest { static boolean flag = false;//非volatile變量 public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { while(!flag){ }; } }).start(); Thread.sleep(100); flag = true; System.out.println("主線程運(yùn)行完畢"); } }
主線程已經(jīng)修改了flag為true,但子線程一直不會(huì)退出循環(huán),因?yàn)樽泳€程一直沒有同步到 主內(nèi)存中的變量的值。
截圖可見程序一直沒有退出,使用dump threads后:
"Thread-0" #12 prio=5 os_prio=0 tid=0x0000000022d89800 nid=0x168 runnable [0x00000000248df000]
java.lang.Thread.State: RUNNABLE
at volatileTest$1.run(volatileTest.java:10)
at java.lang.Thread.run(Thread.java:745)
volatile讀 及時(shí)獲得 主內(nèi)存變量
public class volatileTest { static volatile boolean flag = false;//volatile變量 public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { while(!flag){ }; } }).start(); Thread.sleep(100); flag = true; System.out.println("主線程運(yùn)行完畢"); } }
加了一個(gè)volatile關(guān)鍵字,子線程就能檢測(cè)到flag的變化了。子線程會(huì)退出。
普通讀+sleep
public class volatileTest { static boolean flag = false;//非volatile變量 public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { while(!flag){ try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } }; } }).start(); Thread.sleep(100); flag = true; System.out.println("主線程運(yùn)行完畢"); } }
加了sleep,子線程會(huì)退出。
其實(shí)就算變量不是volatile的,JVM也會(huì)盡量去保證可見性。最開始的例子,由于CPU一直執(zhí)行循環(huán),沒有其他時(shí)間來獲取 主內(nèi)存中的變量的最新值,但加了sleep后,CPU就有時(shí)間去獲取 主內(nèi)存中的東西了。
普通讀+同步塊
public class volatileTest { static boolean flag = false;//非volatile變量 static Object sync = new Object(); public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { while(!flag){ synchronized (sync) {}//隨便synchronized一個(gè)對(duì)象 //synchronized (this)也可以 }; } }).start(); Thread.sleep(100); flag = true; System.out.println("主線程運(yùn)行完畢"); } }
加了同步塊,子線程會(huì)退出。
這是因?yàn)閟ynchronized具體過程是:
- 獲得同步鎖;
- 清空工作內(nèi)存;
- 從主內(nèi)存拷貝對(duì)象副本到工作內(nèi)存;
- 執(zhí)行代碼(計(jì)算或者輸出等);
- 刷新主內(nèi)存數(shù)據(jù);
- 釋放同步鎖。
簡單的說,synchronized進(jìn)入時(shí),會(huì)將 主內(nèi)存中最新的變量,拷貝進(jìn) 自己線程 的工作內(nèi)存。synchronized退出時(shí),會(huì)把 自己線程的工作內(nèi)存的變量 弄進(jìn) 主內(nèi)存中。
同步塊 遭遇 鎖消除
public class volatileTest { static boolean flag = false;//非volatile變量 public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { while(!flag){ synchronized (new Object()){} }; } }).start(); Thread.sleep(100); flag = true; System.out.println("主線程運(yùn)行完畢"); } }
子線程不會(huì)退出。
原因是:synchronized (new Object()){}
中這個(gè)Object永遠(yuǎn)不可能逃逸到同步塊以外去,所以同步操作其實(shí)根本不需要執(zhí)行了,既然沒有執(zhí)行同步,那么相當(dāng)于這里是啥也沒有。
普通讀+System.out.println
public class volatileTest { static boolean flag = false; public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { while(!flag){ System.out.println("子線程running"); }; } }).start(); Thread.sleep(100); flag = true; System.out.println("主線程運(yùn)行完畢"); } }
加了System.out.println
,子線程會(huì)退出。
因?yàn)閛ut這個(gè)PrintStream實(shí)例的println實(shí)現(xiàn)是:
public void println(String x) { synchronized (this) { print(x); newLine(); } }
因?yàn)樗灿型綁K。
到此這篇關(guān)于Java并發(fā)volatile可見性的驗(yàn)證實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java并發(fā)volatile驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA 獲取系統(tǒng)當(dāng)前時(shí)間實(shí)例代碼
這篇文章主要介紹了JAVA 獲取系統(tǒng)當(dāng)前時(shí)間實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10SpringBoot整合WebSocket的客戶端和服務(wù)端的實(shí)現(xiàn)代碼
這篇文章主要介紹了SpringBoot整合WebSocket的客戶端和服務(wù)端的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07使用Spring的攔截器監(jiān)測(cè)每個(gè)Controller或方法的執(zhí)行時(shí)長
這篇文章主要介紹了使用Spring的攔截器監(jiān)測(cè)每個(gè)Controller或方法的執(zhí)行時(shí)長,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java超詳細(xì)教你寫一個(gè)銀行存款系統(tǒng)案例
這篇文章主要介紹了怎么用Java來寫一個(gè)銀行的存款系統(tǒng),銀行存款主要有賬號(hào)和存款金額兩個(gè)屬性,感興趣的朋友跟隨文章往下看看吧2022-03-03使用@DS輕松解決動(dòng)態(tài)數(shù)據(jù)源的問題
這篇文章主要介紹了使用@DS輕松解決動(dòng)態(tài)數(shù)據(jù)源的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Java工具jsch.jar實(shí)現(xiàn)上傳下載
這篇文章主要為大家詳細(xì)介紹了Java操作ftp的一款工具,利用jsch.jar針對(duì)sftp的上傳下載工具類,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12