volatile可見性 在多執行緒中未生效
阿新 • • 發佈:2021-04-24
話說日子一天天過去,小年輕涉足多執行緒快要超兩個小時總計時了。
隨著上次匿名內部類 需要final修飾 的問題 尋找結束,其實當時還涉及到另一個問題。
當時小年輕是為了 研究一下volatile的可見性在多執行緒當中的應用來操作程式碼的。
說到這裡,就要說一說一這個多執行緒會遇到的一些問題。
首先,我們知道當一個執行緒執行到中途時突然睡眠了 ,這是另一個執行緒其實是可以執行的,並且可以使用第一個執行緒所使用的變數。
但是如果這個變數是不可見的 ,那麼另一個執行緒就不會知道變數是否在第一個執行緒中資料已經改變,迭戈執行緒如果後面改變了第一個執行緒的中變數的值,第一個執行緒也不知道。這樣資料就不符合事實,完全不符合全球知識共享的現實,這可不行
這個時候變數的可見性就十分重要,所以volatile就出現了 。
經過volatile修飾的變數會變得在具有可見性,所以無論是第一個執行緒還是第二個執行緒都能隨時看到變數值的改變。
以上內容就是本文最核心知識了,接下來就是小年輕自己的問題: 無需關看
接下來就是問題出現的時候了:
```java 在這裡插入程式碼片 public class VolatieTest { volatile boolean run=true; void m(){ System.out.println("m start"); while(run){ try { //睡十秒 讓另一個執行緒可以在這段時間啟動,會改變變數的值 TimeUnit.SECONDS.sleep(10); System.out.println(run+"rrr"); } catch (InterruptedException e) { e.printStackTrace(); } } //如果在end列印沒有用了10秒則則證明了volatile生效了 while內重新讀取了run的值 System.out.println("m end"); } public static void main(String[] args) { final VolatieTest t = new VolatieTest(); new Thread(new Runnable() { @Override public void run() { t.m(); } }).start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } //趁第一個執行緒睡眠 改變了run的值 //如果重新讀取 則會停止第一個執行緒睡眠 直接輸出end t.run=false; System.out.println("*"); } }
其實程式碼相當的簡單易懂,但是實際過程中,結果並沒有。
從上面程式碼可以看出,正常情況來講 如果生效則應該先列印 m end r然後 * 就結束了
實際結果如下:
這個結果證明 while對run 沒有重讀 但是執行緒內其實是知道run的值發生了改變。
由此,度娘再次上線。
使用volatile的時候 可見性在jdk1.8的時候會強制重新讀取修飾的值 jdk1.7不會
所以在做多執行緒修 用volatile修飾變數 沒能實現變數的可見性的功能
差不多就是這個意思吧