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

資訊專欄INFORMATION COLUMN

理解java Volatile 關鍵字

ConardLi / 1407人閱讀

摘要:最近在看多線程相關,看到這篇來自大神關于關鍵字的講解感覺非常詳細易懂,特此轉載一下。如果對增加聲明則所有線程對的寫都會立即刷新到主存中,而且所有對的讀也都直接從主存中去讀。

最近在看java多線程相關,看到這篇來自大神Jakob Jenkov關于Volatile關鍵字的講解感覺非常詳細易懂,特此轉載一下。
原文鏈接:http://tutorials.jenkov.com/j...

內存可見性問題

在多線程應用中,對于每個非Volatile變量,每個cpu會從內存中拷貝一份副本到cpu的高速緩存中。
假設一種場景,兩個或兩個以上的線程去訪問共享對象SharedObject

public class SharedObject {

    public int counter = 0;

}

線程1去寫counter值,線程1和線程2會不定期的讀counter的值,則有可能存在兩個cpu中緩存的counter值不一樣,cpu1寫入到緩存中的counter值沒有刷新到主存,如下圖的情況:

這就叫可見性問題。

在java中,Volatile關鍵字可以保證變量的可見性。

如果對counter增加Volatile聲明:

public class SharedObject {

    public volatile int counter = 0;

}

則所有線程對counter的寫都會立即刷新到主存中,而且所有對counter的讀也都直接從主存中去讀。

Volatile關鍵字的可見性保證不僅限于被Volatile聲明的變量本身

還有以下兩種變量即使沒有用volatile聲明,也可以得到相應的可見性保證

如果線程A去寫一個volatile變量,隨后線程B去讀這個volatile變量,則所有在線程A寫這個volatile變量之前對線程A可見的變量,在線程B讀這個volatile變量之后也對線程B可見。

如果線程A去讀一個volatile變量,則所有對線程A可見的變量,在線程A讀取這個volatile變量時,會從主存中重新讀一次

晦澀難懂,舉個栗子:

解釋第一條:

public class MyClass {
    private int years;
    private int months
    private volatile int days;


    public void update(int years, int months, int days){
        this.years  = years;
        this.months = months;
        this.days   = days;
    }
}

當days變量被寫入時,years和months因為對當前線程可見,也會被寫入到主存中。

解釋第二條:

ublic 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;
    }
}

totalDays()方法執行時,第一步讀取days的值,因為days時volatile變量,所以所有對當前線程可見的變量都會從主存中重新讀一次。

但是這樣對帶來一個由重排序而產生的新問題

為了提高性能,CPU和JVM都會指令在不影響語義的前提下進行重排序操作,舉個栗子:

上面的update方法可能會被重排序成:(為了方便理解,將參數名加了個new后綴)

public class MyClass {
    private int years;
    private int months
    private volatile int days;


   public void update(int years, int monthsNew, int daysNew){
    this.days   = days;
    this.months = monthsNew;
    this.years  = daysNew;
    }
}

這種情況下雖然在days被寫入的時候,years和months也會被刷新到主存中,但是并不是monthsNew和daysNew的值,這就意味著,這種重排序改變了語義。

重排序問題的解決方案:volatile的 Happens-Before 原則

為解決這個問題,java賦予了volatile變量一些 Happens-Before 原則的保證。
原則如下:

對其它變量的讀和寫操作不能被重排序到對一個volatile變量的寫操作之后。

對其他變量的讀和寫操作不能被重排序到對一個volatile變量的讀操作之前。

注意:兩條原則反過來是不保證的,比如對其它變量的讀和寫操作有可能會被重排序到對一個volatile變量的寫操作之前。

未完待續~~~

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69563.html

相關文章

  • 理解Java中的Volatile鍵字(demo)

    摘要:現在的處理器,一般是會有多個的,每個線程可能運行在不同的,那么線程修改完成的值,是首先保存在中去。考慮這樣一種情況現在有兩個線程,線程和線程,他們不時會去讀取這個共享變量。 什么是volatile 關鍵字volatile 提供了Java 虛擬機中最輕量級的同步機制。在meidium 中有篇文章說:Volatile?specifier?is used to indicate that a...

    codecraft 評論0 收藏0
  • 死磕 java同步系列之volatile解析

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

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

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

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

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

    kviccn 評論0 收藏0
  • 掌握Java的內存模型,你就是解決并發問題最靚的仔

    摘要:掌握的內存模型,你就是解決并發問題最靚的仔編譯優化說的具體一些,這些方法包括和關鍵字,以及內存模型中的規則。掌握的內存模型,你就是解決并發問題最靚的仔共享變量藍色的虛線箭頭代表禁用了緩存,黑色的實線箭頭代表直接從主內存中讀寫數據。 摘要:如果編寫的并發程序出現問題時,很難通過調試來解決相應的問題,此時,需要一行行的檢查代碼...

    番茄西紅柿 評論0 收藏2637

發表評論

0條評論

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