免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
volatile關(guān)鍵字詳解

volatile的三個特點

  1. 保證線程之間的可見性

  2. 禁止指令重排

  3. 不保證原子性

可見性

概念

可見性是多線程場景中才討論的,它表示多線程環(huán)境中,當(dāng)一個線程修改了共享變量的值,其他線程能夠知道這個修改。

為什么需要可見性

緩存一致性問題:

public class Test {    public static void main(String[] args) {        Mythread mythread = new Mythread();        new Thread(() -> {            try {                //延時2s,確保進(jìn)入while循環(huán)                TimeUnit.SECONDS.sleep(2);                //num自增                mythread.increment();                System.out.println("Thread-" + Thread.currentThread().getName() +                        " current num value:" + mythread.num);            } catch (Exception e) {                e.printStackTrace();            }        }, "test").start();        while(mythread.num == 0){             //dead        }        System.out.println("game over!!!");    }}class Mythread{    //不加volatile,主線程無法得知num的值發(fā)生了改變,從而陷入死循環(huán)    volatile int num = 0;    public void increment(){        ++num;    }}

如上述代碼,如果不加volatile,程序運行結(jié)果如下

加上volatile關(guān)鍵字后,程序運行結(jié)果如下

解決方向:

  • 總線鎖:

    一次只有一個線程能通過總線進(jìn)行通信。(效率低,已棄用)

  • MESI緩存一致性協(xié)議,CPU總線嗅探機(jī)制(監(jiān)聽機(jī)制)

    有volatile修飾的共享變量在編譯器編譯后進(jìn)行讀寫操作時,指令會多一個lock前綴,Lock前綴的指令在多核處理器下會引發(fā)兩件事情。


    (參考下面兩位大佬的博客)

    https://blog.csdn.net/jinjiniao1/article/details/100540277

    https://blog.csdn.net/qq_33522040/article/details/95319946

    • 每個處理器通過嗅探在總線上傳播的數(shù)據(jù)來檢查自己緩存的值是不是過期了,當(dāng)處理器發(fā)現(xiàn)自己緩存行對應(yīng)的內(nèi)存地址被修改,就會將當(dāng)前處理器的緩存行設(shè)置為無效狀態(tài), 當(dāng)處理器對這個數(shù)據(jù)進(jìn)行修改操作的時候,會重新從系統(tǒng)內(nèi)存中吧數(shù)據(jù)讀到處理器緩存行里。

    • 處理器使用嗅探技術(shù)保證它的內(nèi)部緩存,系統(tǒng)內(nèi)存和其他處理器的緩存在總線上保持一致

    • 寫一個volatile變量時,JMM(java共享內(nèi)存模型)會把該線程對應(yīng)的本地內(nèi)存中的共享變量值刷新到主內(nèi)存;

    • 當(dāng)讀一個volatile變量時,JMM會把該線程對應(yīng)的本地內(nèi)存置為無效,線程接下來從主內(nèi)存中讀取共享變量。

禁止指令重排

指令重排概念

編譯器和CPU在保證最終結(jié)果不變的情況下,對指令的執(zhí)行順序進(jìn)行重排序。

指令重排的問題

可以與雙重檢驗實現(xiàn)單例模式聯(lián)系起來看:

首先,一個對象的創(chuàng)建過程可大致分為以下三步:

  1. 分配內(nèi)存空間

  2. 執(zhí)行對象構(gòu)造方法,初始化對象

  3. 引用指向?qū)嵗龑ο笤诙阎械牡刂?/p>

但是在實際執(zhí)行過程中,CPU可能會對上述步驟進(jìn)行優(yōu)化,進(jìn)行指令重排

序1->3->2,從而導(dǎo)致引用指向了未初始化的對象,如果這個時候另外一個線

程引用了該未初始化的對象(只執(zhí)行了1->3兩步),就會產(chǎn)生異常。

不保證原子性

為什么無法保證

具體例子

public class Test {    public static void main(String[] args) {        Mythread mythread = new Mythread();        for(int i = 0; i < 6666; ++i){            new Thread(() -> {                try {                    mythread.increment();                } catch (Exception e) {                    e.printStackTrace();                }            }, "test").start();        }        System.out.println("Thread-" + Thread.currentThread().getName() +                " current num value:" + mythread.num);    }}class Mythread{    volatile int num = 0;    public void increment(){        ++num;    }}

上述代碼的運行結(jié)果如下圖

可以看到,循環(huán)執(zhí)行了6666次,但最后的結(jié)果為6663,說明在程序運行過程中出

現(xiàn)了重復(fù)的情況。

解決方案

  1. 使用JUC中的Atomic類(之后會專門寫一篇學(xué)習(xí)筆記進(jìn)行闡述)

  2. 使用synchronized關(guān)鍵字修飾(不推薦)

volatile保證可見性和解決指令重排的底層原理

內(nèi)存屏障(內(nèi)存柵欄)

組成

內(nèi)存屏障分為兩種:Load Barrier 讀屏障Store Barrier 寫屏障

4種類型屏障

種類例子作用
LoadLoad屏障Load1; LoadLoad; Load2保證Load1讀取操作讀取完畢后再去執(zhí)行Load2后續(xù)讀取操作
LoadStore屏障Load1; LoadStore; Store2保證Load1讀取操作讀取完畢后再去執(zhí)行Load2后續(xù)寫入操作
StoreStore屏障Store1; StoreStore; Store2保證Load1的寫入對所有處理器可見后再去執(zhí)行Load2后續(xù)寫入操作
StoreLoad屏障Store1; StoreLoad; Load2保證Load1的寫入對所有處理器可見后再去執(zhí)行Load2后續(xù)讀取操作

作用

  1. 保證特定操作的執(zhí)行順序 

    在每個volatile修飾的全局變量讀操作前插入LoadLoad屏障,在讀操作后插入LoadStore屏障

  2. 保證某些變量的內(nèi)存可見性

    在每個volatile修飾的全局變量寫操作前插入StoreStore屏障,在寫操作后插入StoreLoad屏障

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Java內(nèi)存模型原理,你真的理解嗎?
volatile關(guān)鍵字的作用
面試必問的 volatile,你了解多少?
Java并發(fā)JVM內(nèi)存模型處理器從而實現(xiàn)安全且高效的多線程功能
多線程編程中什么情況下需要加volatile呢?
Java之volatile如何保證可見性和指令重排序
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服