真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

volatile關(guān)鍵字的作用以及對(duì)變量的影響

這篇文章主要為大家分享volatile關(guān)鍵字對(duì)普通全局變量的效果影響。其次介紹了volatile關(guān)鍵字的作用,閱讀完整文相信大家對(duì)volatile關(guān)鍵字了一定的認(rèn)識(shí)。

在岳普湖等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)、做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作按需搭建網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),網(wǎng)絡(luò)營銷推廣,外貿(mào)營銷網(wǎng)站建設(shè),岳普湖網(wǎng)站建設(shè)費(fèi)用合理。

接下來,我們就一起來分析下這個(gè)問題!讓我們先通過一個(gè)例子來回顧下volatile關(guān)鍵字的作用!

public class VolatitleFoo {
    //類變量
    final static int max = 5;
    static int init_value = 0;

    public static void main(String args[]) {
        //啟動(dòng)一個(gè)線程,當(dāng)發(fā)現(xiàn)local_value與init_value不同時(shí),則輸出init_value被修改的值
        new Thread(() -> {
            int localValue = init_value;
            while (localValue < max) {
                if (init_value != localValue) {
                    System.out.printf("The init_value is update ot [%d]\n", init_value);
                    //對(duì)localValue進(jìn)行重新賦值
                    localValue = init_value;
                }
            }
        }, "Reader").start();
        //啟動(dòng)updater線程,主要用于對(duì)init_value的修改,當(dāng)local_value=5的時(shí)候退出生命周期
        new Thread(() -> {
            int localValue = init_value;
            while (localValue < max) {
                //修改init_value
                System.out.printf("The init_value will be changed to [%d]\n", ++localValue);
                init_value = localValue;
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Updater").start();
    }
}

在上面的代碼示例中,我們定義了兩個(gè)類變量max、init_value,然后在主線程中分別啟動(dòng)一個(gè)Reader線程,一個(gè)Updater線程。Updater線程做的事情就是在值小于max的值時(shí)以每兩毫秒的速度進(jìn)行自增。而Reader線程則是在感知init_value值發(fā)生變化的情況下進(jìn)行讀取操作。

期望的效果是線程Updater更新init_value值之后,可以立刻被線程Reader感知到,從而進(jìn)行輸出顯示。實(shí)際運(yùn)行效果如下:

The init_value will be changed to [1]
The init_value will be changed to [2]
The init_value will be changed to [3]
The init_value will be changed to [4]
The init_value will be changed to [5]

實(shí)際的運(yùn)行效果是在Updater修改類變量init_value后,Reader線程并沒有立馬感知到變化,所以沒有進(jìn)行相應(yīng)的顯示輸出。而原因就在于共享類變量init_value在被線程Updater拷貝到該線程的工作內(nèi)存中后,Updater對(duì)變量init_value的修改都是在工作內(nèi)存中進(jìn)行的,完成操作后沒有立刻同步回主內(nèi)存,所以Reader線程對(duì)其改變并不可見。

為了解決線程間對(duì)類變量init_value的可見性問題,我們將類變量init_value用volatile關(guān)鍵字進(jìn)行下修飾,如下:

static volatile int init_value = 0;

然后我們?cè)龠\(yùn)行下代碼,看看結(jié)果:

The init_value will be changed to [1]
The init_value is update ot [1]
The init_value will be changed to [2]
The init_value is update ot [2]
The init_value will be changed to [3]
The init_value is update ot [3]
The init_value will be changed to [4]
The init_value is update ot [4]
The init_value will be changed to [5]
The init_value is update ot [5]

此時(shí)線程Updater對(duì)類變量init_value的修改,立馬就能被Reader線程感知到了,這就是volatile關(guān)鍵字的效果,可以讓共享變量在線程間實(shí)現(xiàn)可見,原因就在于在JVM的語義層面要求被volatile修飾的共享變量,在工作內(nèi)存中的修改要立刻同步回主內(nèi)存,并且讀取也需要每次都重新從主內(nèi)存中刷新一份到工作內(nèi)存中后才可以操作。

關(guān)于以上適用volatile關(guān)鍵字修飾基本類型的類變量、實(shí)例變量的場景,相信大家會(huì)比較好理解。接下來,我們來繼續(xù)改造下代碼:

public class VolatileEntity {
    //使用volatile修飾共享資源i
    //類變量
    final static int max = 5;
    int init_value = 0;
    public static int getMax() {
        return max;
    }
    public int getInit_value() {
        return init_value;
    }
    public void setInit_value(int init_value) {
        this.init_value = init_value;
    }
    private static class VolatileEntityHolder {
        private static VolatileEntity instance = new VolatileEntity();
    }
    public static VolatileEntity getInstance() {
        return VolatileEntityHolder.instance;
    }
}

我們將之前代碼中的類變量init_value放到實(shí)體類VolatileEntity中,并將其設(shè)計(jì)為一個(gè)實(shí)例變量,為了便于理解,我們將實(shí)體類VolatileEntity設(shè)計(jì)為單例模式,確保兩個(gè)線程操作的是同一個(gè)共享堆內(nèi)存對(duì)象。如下:

public class VolatileEntityTest {

    //使用volatile修飾共享資源
    private static VolatileEntity volatileEntity = VolatileEntity.getInstance();

    private static final CountDownLatch latch = new CountDownLatch(10);

    public static void main(String args[]) throws InterruptedException {
        //啟動(dòng)一個(gè)線程,當(dāng)發(fā)現(xiàn)local_value與init_value不同時(shí),則輸出init_value被修改的值
        new Thread(() -> {
            int localValue = volatileEntity.init_value;
            while (localValue < VolatileEntity.max) {
                if (volatileEntity.init_value != localValue) {
                    System.out.printf("The init_value is update ot [%d]\n", volatileEntity.init_value);
                    //對(duì)localValue進(jìn)行重新賦值
                    localValue = volatileEntity.init_value;
                }
            }
        }, "Reader").start();

        //啟動(dòng)updater線程,主要用于對(duì)init_value的修改,當(dāng)local_value=5的時(shí)候退出生命周期
        new Thread(() -> {
            int localValue = volatileEntity.init_value;
            while (localValue < VolatileEntity.max) {
                //修改init_value
                System.out.printf("The init_value will be changed to [%d]\n", ++localValue);
                volatileEntity.init_value = localValue;
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Updater").start();
    }
}

在上述代碼中線程Updater和Reader此時(shí)操作的是類變量VolatileEntity對(duì)象中的普通實(shí)例變量init_value。在VolatileEntity對(duì)象沒被volatile關(guān)鍵字修飾之前,我們看下運(yùn)行效果:

The init_value will be changed to [1]
The init_value will be changed to [2]
The init_value will be changed to [3]
The init_value will be changed to [4]
The init_value will be changed to [5]

與未被volatile修飾的int類型的類變量效果一樣,線程Updater對(duì)VolatileEntity對(duì)象中init_value變量的操作也不能立馬被線程Reader可見。如果此時(shí)我們不VolatileEntity類中單獨(dú)用volatile關(guān)鍵字修飾init_value變量,而是直接VolatileEntity對(duì)象用volatile關(guān)鍵字修飾,效果會(huì)如何呢?

private static volatile VolatileEntity volatileEntity = VolatileEntity.getInstance();

此時(shí)VolatileEntity對(duì)象的引用變量被volatile關(guān)鍵字修飾了,然而其中的普通實(shí)例變量init_value并沒有直接被volatile關(guān)鍵字修飾,然后我們?cè)谶\(yùn)行下代碼看看效果:

The init_value will be changed to [1]
The init_value is update ot [1]
The init_value will be changed to [2]
The init_value is update ot [2]
The init_value will be changed to [3]
The init_value is update ot [3]
The init_value will be changed to [4]
The init_value is update ot [4]
The init_value will be changed to [5]
The init_value is update ot [5]

從實(shí)際的運(yùn)行效果上看,雖然我們沒有直接用volatile關(guān)鍵字修飾對(duì)象中的類變量init_value,而是修改了對(duì)象的引用,但是我們看到對(duì)象中的普通實(shí)例變量仍然實(shí)行了線程間的可見性,也就是說間接也相當(dāng)于被volatile關(guān)鍵字修飾了。所以,在這里問題也就基本上有了答案,那就是:“被volatile關(guān)鍵字修飾的對(duì)象作為類變量或?qū)嵗兞繒r(shí),其對(duì)象中攜帶的類變量和實(shí)例變量也相當(dāng)于被volatile關(guān)鍵字修飾了”。

看完上述內(nèi)容,你們對(duì)volatile關(guān)鍵字有進(jìn)一步的了解嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀。


標(biāo)題名稱:volatile關(guān)鍵字的作用以及對(duì)變量的影響
文章源于:http://weahome.cn/article/iphhjg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部