最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳細分析java并發(fā)之volatile關(guān)鍵字

 更新時間:2020年06月24日 10:41:52   作者:onlythinking  
這篇文章主要介紹了java并發(fā)之volatile關(guān)鍵字的的相關(guān)資料,文中代碼非常詳細,幫助大家更好的理解和學習,感興趣的朋友可以了解下

Java面試中經(jīng)常會涉及關(guān)于volatile的問題。本文梳理下volatile關(guān)鍵知識點。

volatile字意為“易失性”,在Java中用做修飾對象變量。它不是Java特有,在C,C++,C#等編程語言也存在,只是在其它編程語言中使用有所差異,但總體語義一致。比如使用volatile 能阻止編譯器對變量的讀寫優(yōu)化。簡單說,如果一個變量被修飾為volatile,相當于告訴系統(tǒng)說我容易變化,編譯器你不要隨便優(yōu)化(重排序,緩存)我。

Happens-before

規(guī)范上,Java內(nèi)存模型遵行happens-before。

volatile變量在多線程中,寫線程和讀線程具有happens-before關(guān)系。也就是寫值的線程要在讀取線程之前,并且讀線程能完全看見寫線程的相關(guān)變量。

happens-before:如果兩個有兩個動作AB,A發(fā)生在B之前,那么A的順序應該在B前面并且A的操作對B完全可見。

happens-before 具有傳遞性,如果A發(fā)生在B之前,而B發(fā)生在C之前,那么A發(fā)生在C之前。

如何保證可見性

多線程環(huán)境下counter變量的更新過程。線程1先從主存拷貝副本到CPU緩存,然后CPU執(zhí)行counter=7,修改完后寫入CPU緩存,等待時機同步到主存。在線程1同步主存前,線程2讀到counter值依然為0。此時已經(jīng)發(fā)生內(nèi)存一致性錯誤(對于相同的共享數(shù)據(jù),多線程讀到視圖不一致)。因為線程2看不見線程1操作結(jié)果,也將這個問題稱為可見性問題。

public class SharedObject {
  public int counter = 0;
}

因為多了緩存優(yōu)化導致,導致可見性問題。所以volatile通過消除緩存(描述可能不太準確)來避免。例如當使用volatile修飾變量后,操作該變量讀寫直接與主存交互,跳過緩存層,保證其它讀線程每次獲取的都是最新值。

public volatile int counter = 0;

volatile 不單只消除修飾的變量的緩存。事實上與之相關(guān)的變量在讀寫時也會消除緩存,如同使用了volatile一樣。

如下 years,months,days 三個變量中只有days是volatile,但是對years,months讀寫操作也和days時也會跳過緩存,其它線程每次讀到的都是最新值。

public class MyClass {
  private int years;
  private int months
  private volatile int days;
  public int totalDays() {
    int total = this.days;
    total += months * 30;
    total += years * 365;
    return total;
  }
  public void update(int years, int months, int days){
    this.years = years;
    this.months = months;
    this.days  = days;
  }
}

這是為什么?我們分析一下。

一個寫線程調(diào)用 update,讀線程調(diào)用totalDays。單線程中,對于update方法,wa與wb存在happens-before關(guān)系, wa在 wb 之前執(zhí)行并對wb可見。

多線程中rc與wb存在happens-before關(guān)系,wb在rc之前執(zhí)行并對rc可見。根據(jù) happens-before傳遞性,wa需要在rc前先執(zhí)行并對rc可見。

因為wb是volatile變量,所以rc獲取的years,months也是最新值。

 

我們知道出于性能原因,JVM和CPU會對程序中的指令進行重新排序。如果update方法里面wa和wb順序被重排,那它們的happens-before關(guān)系將不在成立。

為了避免這個問題,volatile對重排序做了保證 對于發(fā)生在volatile變量操作前的其他變量的操作不能重新排序。

由此我們得到volatile通過消除緩存和防止重排保證線程的可見性。

volatile保證線程安全?

討論線程安全,大家都會提及原子性,順序性,可見性。volatile側(cè)重于保證可見性,也就是當寫的線程更新后,讀線程總能獲得最新值。在只有一個線程寫,多個線程讀的場景下,volatile能滿足線程安全??扇绻鄠€線程同時寫入volatile變量時,則需要引入同步語義才能保證線程安全。

模擬10個線程同時寫入volatile變量,一個線程讀counter,執(zhí)行完后正確結(jié)果應該是counter=10。

  public static class WriterTask implements Runnable {
    private final ShareObject share;
    private final CountDownLatch countDownLatch;
    public WriterTask(ShareObject share, CountDownLatch countDownLatch) {
      this.share = share;
      this.countDownLatch = countDownLatch;
    }
    @Override
    public void run() {
      countDownLatch.countDown();
      share.increase();
    }
  }
  
  public class ShareObject {
    private volatile int counter;
    public void increase() {
      this.counter++;
    }
  }

執(zhí)行結(jié)果出現(xiàn)counter=5或6 錯誤結(jié)果。

通過 synchronized,Lock或AtomicInteger 原子變量保證了結(jié)果的正確。

完整demo https://gist.github.com/onlythinking/ba7ca7aa5faf00a58f4cedae474fa6f6

volatile性能

volatile變量帶來可見性的保證,訪問volatile變量還防止了指令重排序。不過這一切是以犧牲優(yōu)化(消除緩存,直接操作主存開銷增加)為代價,所以不應該濫用volatile,僅在確實需要增強變量可見性的時候使用。

總結(jié)

本文記錄了volatile變量通過消除緩存,防止指令重排序來保證線程可見性,并且在多線程寫入的變量的場景下,不保證線程安全。

歡迎大家留言交流,一起學習分享!??!

以上就是詳細分析java并發(fā)之volatile關(guān)鍵字的詳細內(nèi)容,更多關(guān)于JAVA volatile關(guān)鍵字的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java 中枚舉類enum的values()方法的詳解

    java 中枚舉類enum的values()方法的詳解

    這篇文章主要介紹了java 中枚舉類enum的values()方法的詳解的相關(guān)資料,希望通過本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • java針對電話號碼正則匹配實例

    java針對電話號碼正則匹配實例

    這篇文章主要介紹了java針對電話號碼正則匹配的方法,涉及java正則匹配與字符串操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • java中重寫父類方法加不加@Override詳解

    java中重寫父類方法加不加@Override詳解

    這篇文章主要介紹了java中重寫父類方法加不加@Override詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 一文帶你全面了解Java?Properties類

    一文帶你全面了解Java?Properties類

    Properties是JDK1.0中引入的java類,目前也在項目中大量使用,主要用來讀取外部的配置,那除了這個,你對它其他的一些api也了解嗎??你了解它是怎么實現(xiàn)的嗎??如果不清楚的話,就通過本篇文章帶你一探究竟
    2022-09-09
  • 關(guān)于Controller層和Service層的類報錯問題及解決方案

    關(guān)于Controller層和Service層的類報錯問題及解決方案

    這篇文章主要介紹了關(guān)于Controller層和Service層的類報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • SpringBoot統(tǒng)一功能處理的方式詳解

    SpringBoot統(tǒng)一功能處理的方式詳解

    這篇文章主要為大家詳細介紹了SpringBoot統(tǒng)一功能處理的方式,文中的示例代碼講解詳細,對我們學習或工作有一定借鑒價值,需要的可以參考一下
    2022-08-08
  • SpringBoot項目打jar包與war包的詳細步驟

    SpringBoot項目打jar包與war包的詳細步驟

    SpringBoot和我們之前學習的web應用程序不一樣,其本質(zhì)上是一個 Java應用程序,那么又如何部署呢?這篇文章主要給大家介紹了關(guān)于SpringBoot項目打jar包與war包的詳細步驟,需要的朋友可以參考下
    2023-02-02
  • SpringBoot整合MongoDB全過程

    SpringBoot整合MongoDB全過程

    這篇文章主要介紹了SpringBoot整合MongoDB全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 詳解Java動態(tài)代理的實現(xiàn)及應用

    詳解Java動態(tài)代理的實現(xiàn)及應用

    這篇文章主要介紹了詳解Java動態(tài)代理的實現(xiàn)及應用的相關(guān)資料,希望通過本文大家能理解掌握Java動態(tài)代理的使用方法,需要的朋友可以參考下
    2017-09-09
  • @Scheduled定時器原理及@RefreshScope相互影響

    @Scheduled定時器原理及@RefreshScope相互影響

    這篇文章主要為大家介紹了@Scheduled定時器原理及@RefreshScope相互影響詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07

最新評論

敦煌市| 南京市| 孟连| 冷水江市| 靖宇县| 松江区| 岚皋县| 岐山县| 师宗县| 凭祥市| 马鞍山市| 汉源县| 长汀县| 会同县| 玉林市| 罗定市| 江安县| 上虞市| 普宁市| 揭阳市| 龙岩市| 丰台区| 井研县| 东丰县| 巴林左旗| 临潭县| 楚雄市| 德清县| 义乌市| 布拖县| 大石桥市| 昆明市| 交口县| 天水市| 疏附县| 墨竹工卡县| 韶山市| 镇宁| 衡南县| 尉犁县| 牙克石市|