溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java中的volatile關(guān)鍵字怎么使用

發(fā)布時(shí)間:2021-12-14 13:01:52 來(lái)源:億速云 閱讀:120 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容介紹了“java中的volatile關(guān)鍵字怎么使用”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

1.volatile實(shí)現(xiàn)可見(jiàn)性的原理是什么?

volatile變量修飾的共享變量進(jìn)行寫操作的時(shí)候匯編代碼會(huì)多出一個(gè)Lock前綴指令。

在該指令下,多核處理器會(huì)引發(fā)兩件事:

  • 將當(dāng)前處理器緩存行的數(shù)據(jù)寫回系統(tǒng)內(nèi)存

  • 這個(gè)寫回內(nèi)存的操作會(huì)使在其他CPU里緩存了該內(nèi)存地址的數(shù)據(jù)無(wú)效

這里需要簡(jiǎn)單了解CPU緩存一致性問(wèn)題:多核處理器環(huán)境下,每個(gè)CPU都有自己的緩存行,緩存了內(nèi)存中的數(shù)據(jù),要維護(hù)多個(gè)CPU中緩存的數(shù)據(jù)一致性,就需要解決兩個(gè)問(wèn)題:

  • 一是寫傳播(某個(gè)CPU里的cache數(shù)據(jù)更新時(shí),需要傳播到其他CPU的cache中);

  • 二是事務(wù)的串行化執(zhí)行(在某個(gè)CPU里對(duì)數(shù)據(jù)的修改,在其他CPU中看起來(lái)順序是一樣的,也就是要引入近似[鎖]的概念,保證同一時(shí)刻只有一個(gè)CPU可以對(duì)數(shù)據(jù)做修改);

寫傳播是通過(guò)[總線嗅探]完成的:通過(guò)總線把修改數(shù)據(jù)的事件廣播通知給其他所有的核心,每個(gè)CPU核心都會(huì)監(jiān)聽(tīng)總線上的廣播事件,并檢查是否有相同的數(shù)據(jù)在自己的Cache里面;而事務(wù)的串行化則通過(guò)[MESI協(xié)議]來(lái)完成。

MESI(Modified(已修改)、Exclusive(獨(dú)占)、Shared(共享)、Ivalidated(已失效))協(xié)議中,如果要修改一個(gè)共享數(shù)據(jù),不能直接修改,要先向其他CPU廣播一個(gè)請(qǐng)求,把其他CPU cache中對(duì)應(yīng)的數(shù)據(jù)狀態(tài)改為Invalidated;以后其他CPU在讀取標(biāo)記為Invalidated的數(shù)據(jù)時(shí),需要強(qiáng)制從內(nèi)存中讀取數(shù)據(jù)。

java中的volatile關(guān)鍵字怎么使用

2.演示volatile的可見(jiàn)性

public class VolatileDemo {
    static  int flag = 1;  // 定義一個(gè)共享變量
    public static void main(String[] args) {
        // 兩個(gè)線程,一個(gè)線程負(fù)責(zé)讀取flag的值,另一個(gè)線程負(fù)責(zé)修改flag的值
        new Thread(){
            int localflag = flag;
            @Override
            public void run() {
                while(true){
                    //flag被修改后就跟localflag不一樣了
                    if(localflag!=flag){
                        System.out.println("讀到了flag修改后的值:"+ flag);
                        //把讀到的值賦值給本地變量
                        localflag = flag;
                    }
                }
            }
        }.start();

        new Thread(){
            int localflag = flag;
            @Override
            public void run() {
                while (true){
                    //一直對(duì)flag的值進(jìn)行修改
                    System.out.println("對(duì)flag的值進(jìn)行修改:"+ ++localflag);
                    flag = localflag;
                    //休眠一秒更好地觀察結(jié)果
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();


    }
}

java中的volatile關(guān)鍵字怎么使用

可以看到另一個(gè)線程并不能及時(shí)讀取到被修改的值。

共享變量用volatile修飾后:

public class VolatileDemo {
    static  volatile int flag = 1;
    public static void main(String[] args) {
        // 兩個(gè)線程,一個(gè)線程負(fù)責(zé)讀取flag的值,另一個(gè)線程負(fù)責(zé)修改flag的值
        new Thread(){
            int localflag = flag;
            @Override
            public void run() {
                while(true){
                    //flag被修改后就跟localflag不一樣了
                    if(localflag!=flag){
                        System.out.println("讀到了flag修改后的值:"+ flag);
                        //把讀到的值賦值給本地變量
                        localflag = flag;
                    }
                }
            }
        }.start();

        new Thread(){
            int localflag = flag;
            @Override
            public void run() {
                while (true){
                    //一直對(duì)flag的值進(jìn)行修改
                    System.out.println("對(duì)flag的值進(jìn)行修改:"+ ++localflag);
                    flag = localflag;
                    //休眠一秒更好地觀察結(jié)果
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();


    }
}

java中的volatile關(guān)鍵字怎么使用

可以看到用volatile修飾后,每次另一個(gè)線程總能讀取到修改后的值。

“java中的volatile關(guān)鍵字怎么使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI