最近在oschina問答板塊看到了一個關於java變量在工做內存和主存中的可見性問題:synchorized,sleep 也能達到volatile 線程可見性的目的?,大體的問題描述以下:java
package com.test; import java.util.concurrent.TimeUnit; public class test1 { private static boolean is = true; public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { int i = 0; while(test1.is){ i++; 1 //synchronized (this) { } 會強制刷新主內存的變量值到線程棧? 2 //System.out.println("1"); println 是synchronized 的,會強制刷新主內存的變量值到線程棧? 3 //sleep 會重新load主內存的值? // try { // TimeUnit.MICROSECONDS.sleep(1); // }catch (InterruptedException e) { // e.printStackTrace(); // } } } }).start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(new Runnable() { @Override public void run() { is = false; //設置is爲false,使上面的線程結束while循環 } }).start(); } }
問: 爲何整個程序不會終止? 爲何取消註釋中的任何一個代碼塊(1,2,3),程序纔會終止?synchronized 會強制刷新住內存的變量值到線程棧? sleep 會幹什麼呢?ide
volatile:此關鍵字保證了變量在線程的可見性,全部線程訪問由volatile修飾的變量,都必須從主存中讀取後操做,並在工做內存修改後當即寫回主存,保證了其餘線程的可見性,一樣效果的關鍵字還有final。學習
synchronized:全部同步操做都必須保證 一、原子性 二、可見性,因此在同步塊中發生的變化會立馬寫回主存優化
sleep:此方法只會讓出CPU執行時間,並不會釋放鎖。this
Q1:爲何註釋代碼後程序不會終止?spa
A1:由於 boolean is=true 的變量值被前面線程(簡稱線程A)加載到本身的工做內存,在後面的線程(簡稱線程B)改變 boolean is=false 以後不必定會立馬寫入主存(不過這道題中應該會立刻寫入主存,由於線程執行完 is=false以後線程就要退出了),即使立馬寫入了主存後線程A也不必定立刻load到工做內存中,因此程序一直不會終止?這個是咱們大多數人想到的,但其實JVM針對如今的硬件水平已經作了很大程度的優化,基本上很大程度的保障了工做內存和主內存的及時同步,至關於默認使用了volatile。但只是最大程度!在CPU資源一直被佔用的時候,工做內存與主內存中間的同步,也就是變量的可見性就會不那麼及時!後面會驗證結論。.net
Q2:爲何取消註釋中的任何一個代碼塊(1,2,3),程序纔會終止?線程
A2:行號爲一、2的代碼有一個共同特色,就是都涉及到了synchronized 同步鎖,那麼是否像提問做者猜測的那樣synchronized會強制刷新主內存的變量值到線程棧?
,以及sleep方法也會刷新主存的變量值到線程棧呢?
,事實上咱們前面說了synchronized只會保證在同步塊
中的變量的可見性,而is
變量並不在該同步塊中,因此顯然不是這個致使的。接下來咱們在代碼i++;
後面加上如下代碼:code
for(int k=0;k<100000;k++){ new Object(); }
再Run,程序馬上終止!爲何?在上面的 A1 中咱們已經說了即使有JVM的優化,但當CPU一直被佔用的時候,數據的可見性得不到很好的保證,就像上面的程序一直循環作i++;運算
佔用CPU,而爲何加上上面的代碼後程序就會中止呢?由於對於大量new Object()操做來講,CPU已經不是主要佔時間的操做,真正的耗時應該在內存的分配上(由於CPU的處理速度明顯快過內存,否則也不會有CPU的寄存器了)
,因此CPU空閒後會遵循JVM優化基準,儘量快的保證數據的可見性,從而從主存同步is變量到工做內存,最終致使程序結束,這也是爲何sleep()
方法雖然沒有涉及同步操做,可是依然可使程序終止,由於sleep()
方法會釋放CPU,但不釋放鎖!orm
技術在於不斷的學習和成長,堅持寫博客 和技術輸出,對本身的成長會有很大幫助,若有錯誤 歡迎指正,拒絕人身攻擊。