国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

關(guān)于volatile的理解

LiveVideoStack / 816人閱讀

摘要:但在多線程環(huán)境中就可能出現(xiàn)問題如下面代碼線程語句語句線程線程中的語句和語句并沒有數(shù)據(jù)依賴關(guān)系,所以可能會進行指令重排序,先去執(zhí)行語句,而這時線程會以為線程已經(jīng)執(zhí)行完而去執(zhí)行這樣就導(dǎo)致程序出錯。

經(jīng)常會聽到volatile這個關(guān)鍵字,但沒有深入的去了解過它,今天好好的整理一下
要談volatile,我們先談?wù)勊睦洗蟾鐂ynchronized
一.synchronized

并發(fā)編程中最重要的三個特性是什么?原子性,可見性,有序性。只要有一個不能保證,就有可能導(dǎo)致程序的運行錯誤,我們熟知的synchronized就能保障原子性,可見性,有序性,因為synchronized能保障任意一個時刻只有一個線程執(zhí)行該代碼塊,自然就不存在原子性的問題,又因為在釋放鎖之前會將變量的修改刷新到主存中,因此保證可見性,又因為每一時刻只有一個線程在執(zhí)行代碼,相當于讓線程順序執(zhí)行同步代碼,所以也可以保證有序性。所以synchronized可保證原子性,可見性,有序性

二.volatile

volatile可以說是一個稍弱的同步機制,因為它可以保障可見性和有序性,不能保障原子性

1.volatile可見性

先看下圖,java中所有的變量都存儲在主內(nèi)存區(qū),在多線程環(huán)境中,還有自己的工作內(nèi)存,線程操作變量時是從主存中拷貝變量到工作內(nèi)存操作,這樣很容易產(chǎn)生"臟讀"的問題。synchronized解決此問題的方法上面也談到了,volatile是如何保證的呢?當一個變量被volatile修飾時,它會保證每次被修改的值會被立刻更新到主存,而且當緩存1對某個變量進行修改時,其它線程的工作內(nèi)存中的該變量的緩存行無效(反映到硬件層的話,就是CPU的L1或者L2緩存中對應(yīng)的緩存行無效),緩存2發(fā)現(xiàn)自己的變量無效后會等待緩存行對應(yīng)的主存地址被更新后從主存中讀取最新值,這樣就保證了可見性

2.volatile有序性

說到volatile的有序性就要提到指令重排序(Instruction Reorder),什么是指令重排序?這是JVM為了提高代碼的執(zhí)行效率對代碼進行的優(yōu)化,它不能保證代碼先后順序執(zhí)行的一致,但可以保證執(zhí)行的結(jié)果和順序執(zhí)行的結(jié)構(gòu)一致。但在多線程環(huán)境中就可能出現(xiàn)問題,如下面代碼

        //線程1
        func1();               語句1
        boolean flag = true;   語句2

        //線程2
        while (!flag){
            sleep();
        }
        func2();

線程1中的語句1和語句2并沒有數(shù)據(jù)依賴關(guān)系,所以可能會進行指令重排序,先去執(zhí)行語句2,而這時線程2會以為線程1已經(jīng)執(zhí)行完func1()而去執(zhí)行func2(),這樣就導(dǎo)致程序出錯。
volatile關(guān)鍵字修飾的變量能禁止指令重排序,這樣就在一定程度上保證了有序性
應(yīng)用:

(1)狀態(tài)標記量
        //線程1
        func1();                        語句1
        boolean volatile flag = true;   語句2

        //線程2
        while (!flag){
            sleep();
        }
        func2();
這是對上面程序的改進,避免了程序出錯

(2)單例模式中的雙重校驗鎖

public class Singleton3 {
    private Singleton3(){}
    private static volatile Singleton3 instance = null;

    public static Singleton3 getInstance() {
        if(instance == null){
            synchronized (Singleton3.class){
                instance = new Singleton3();
            }
        }
        return instance;
    }
}

我們看到已經(jīng)有synchronizd來保證線程同步,為什么還需要volatile來修飾變量instance呢?
原因在 instance = new Singleton3();這句,JVM實際上對它進行了如下操作

(1)給instance分配內(nèi)存
(2)調(diào)用Singleton3的構(gòu)造函數(shù)完成初始化成員變量
(3)將instance指向內(nèi)存分配空間

但由于JVM存在指令重排序優(yōu)化,執(zhí)行的順序可能就為1-3-2,就可能發(fā)生當3執(zhí)行完另一個線程以為它已經(jīng)執(zhí)行完了,搶占當前線程,這時instance非null但沒有初始化,所以另一個線程和以后的線程都會直接返回該沒有初始化的instance,從而出現(xiàn)錯誤。當有volatile修飾變量instance,就可以禁止指令重排序,從而避免出錯。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69079.html

相關(guān)文章

  • 死磕 java同步系列之volatile解析

    摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請參考死磕同步系列之。目前國內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實現(xiàn)原理? (4)volatile的缺陷? 簡介 volatile...

    番茄西紅柿 評論0 收藏0
  • 死磕 java同步系列之volatile解析

    摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請參考死磕同步系列之。目前國內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實現(xiàn)原理? (4)volatile的缺陷? 簡介 volatile...

    番茄西紅柿 評論0 收藏0
  • 死磕 java同步系列之volatile解析

    摘要:前半句是指線程內(nèi)表現(xiàn)為串行的語義,后半句是指指令重排序現(xiàn)象和工作內(nèi)存和主內(nèi)存同步延遲現(xiàn)象。關(guān)于內(nèi)存模型的講解請參考死磕同步系列之。目前國內(nèi)市面上的關(guān)于內(nèi)存屏障的講解基本不會超過這三篇文章,包括相關(guān)書籍中的介紹。問題 (1)volatile是如何保證可見性的? (2)volatile是如何禁止重排序的? (3)volatile的實現(xiàn)原理? (4)volatile的缺陷? 簡介 volatile...

    kviccn 評論0 收藏0
  • 理解java Volatile 關(guān)鍵字

    摘要:最近在看多線程相關(guān),看到這篇來自大神關(guān)于關(guān)鍵字的講解感覺非常詳細易懂,特此轉(zhuǎn)載一下。如果對增加聲明則所有線程對的寫都會立即刷新到主存中,而且所有對的讀也都直接從主存中去讀。 最近在看java多線程相關(guān),看到這篇來自大神Jakob Jenkov關(guān)于Volatile關(guān)鍵字的講解感覺非常詳細易懂,特此轉(zhuǎn)載一下。原文鏈接:http://tutorials.jenkov.com/j... 內(nèi)存可...

    ConardLi 評論0 收藏0
  • 關(guān)于ConcurrentHashMap1.8個人理解

    摘要:數(shù)據(jù)結(jié)構(gòu)重要成員變量代表整個哈希表。科普,解決多線程并行情況下使用鎖造成性能損耗的一種機制,操作包含三個操作數(shù)內(nèi)存位置預(yù)期原值和新值。 ConcurrenHashMap 。下面分享一下我對ConcurrentHashMap 的理解,主要用于個人備忘。如果有不對,請批評。 HashMap嚴重的勾起了我對HashMap家族的好奇心,下面分享一下我對ConcurrentHashMap 的理解...

    olle 評論0 收藏0

發(fā)表評論

0條評論

LiveVideoStack

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<