摘要:內存語義的的實現可見性的實現基于的讀取,寫入兩個操作的內存語義。首先,對中內存屏障的介紹內存屏障用于控制特定條件下的重排序和內存可見性問題。在大多數處理器的實現中,這個屏障是個萬能屏障,兼具其它三種內存屏障的功能。
volatile,可見性,有序性 volatile的特性
可見性:對一個volatile變量的讀,總能獲取其他任意線程對該變量最后的寫入。
有序性:JMM會限制volatile變量相關的編譯器重排序和處理器重排序。
內存語義的的實現volatile寫的內存語義:當寫入一個volatile變量的時候,JMM將線程工作內存中的該變量的值刷新到主內存。
volatile讀的內存語義:當讀取一個volatile變量的時候,JMM首先將該線程工作內存中的這個變量設置為無效,迫使該線程重新從主內存獲取最新的有效值。
兩者結合起來,就實現了,volatile變量的可見性,因為一個線程去讀取volatile變量的時候獲取的肯定是最新的值。
能否重排序 | - | 第二個操作 | - |
---|---|---|---|
第一個操作 | 普通讀/寫 | volatile讀 | volatile寫 |
普通讀/寫 | NO | ||
volatile讀 | NO | NO | NO |
volatile寫 | NO | NO |
理解JMM如何實現volatile的兩層內存語義的關鍵是==內存屏障==。volatile的兩層內存語義都是使用內存屏障來實現的。
LoadLoad屏障:對于這樣的語句Load1; LoadLoad; Load2,在Load2及后續讀取操作要讀取的數據被訪問前,保證Load1要讀取的數據被讀取完畢。
StoreStore屏障:對于這樣的語句Store1; StoreStore; Store2,在Store2及后續寫入操作執行前,保證Store1的寫入操作對其它處理器可見。
LoadStore屏障:對于這樣的語句Load1; LoadStore; Store2,在Store2及后續寫入操作被刷出前,保證Load1要讀取的數據被讀取完畢。
StoreLoad屏障:對于這樣的語句Store1; StoreLoad; Load2,在Load2及后續所有讀取操作執行前,保證Store1的寫入對所有處理器可見。它的開銷是四種屏障中最大的。 在大多數處理器的實現中,這個屏障是個萬能屏障,兼具其它三種內存屏障的功能。
volatile寫操作前面插入一個StoreStore屏障
對比StoreStore屏障的定義,這里的volatile寫是那個Store2,該屏障保證在volatile寫執行之前,Store1的寫入操作對其他處理器可見,那么可以得出,該屏障不僅保證了Store1已經執行完畢(有序性),也保證了可見性。
每個volatile寫操作的后面插入一個StoreLoad屏障
對比StoreLoad屏障的定義,這里的volatile寫是那個Store1,該屏障也保證了有序性和可見性。其他都是類似的。
每個volatile讀操作后面插入一個LoadLoad屏障。
每個volatile讀操作后面插入一個LoadStore屏障。
//假設有個volatile變量instance,對其進行寫操作 instance = new Singleton();
在X86處理器下看看其對應的匯編代碼的一部分:
lock add1 $0*0
lock前綴的指令在多核處理器下引發了兩件事:
當前處理器緩存行的數據寫回系統內存
使其他處理器緩存行中緩存的該內存地址的數據無效
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69347.html
摘要:有可能一個線程中的動作相對于另一個線程出現亂序。當實際輸出取決于線程交錯的結果時,這種情況被稱為競爭條件。這里的問題在于代碼塊不是原子性的,而且實例的變化對別的線程不可見。這種不能同時在多個線程上執行的部分被稱為關鍵部分。 為什么要額外寫一篇文章來研究volatile呢?是因為這可能是并發中最令人困惑以及最被誤解的結構。我看過不少解釋volatile的博客,但是大多數要么不完整,要么難...
摘要:但在多線程環境中就可能出現問題如下面代碼線程語句語句線程線程中的語句和語句并沒有數據依賴關系,所以可能會進行指令重排序,先去執行語句,而這時線程會以為線程已經執行完而去執行這樣就導致程序出錯。 經常會聽到volatile這個關鍵字,但沒有深入的去了解過它,今天好好的整理一下要談volatile,我們先談談它的老大哥synchronized一.synchronized 并發編程中最重要的...
摘要:文章簡介分析的作用以及底層實現原理,這也是大公司喜歡問的問題內容導航的作用什么是可見性源碼分析的作用在多線程中,和都起到非常重要的作用,是通過加鎖來實現線程的安全性。而的主要作用是在多處理器開發中保證共享變量對于多線程的可見性。 文章簡介 分析volatile的作用以及底層實現原理,這也是大公司喜歡問的問題 內容導航 volatile的作用 什么是可見性 volatile源碼分析 ...
摘要:內存模型是圍繞著在并發過程中如何處理原子性可見性和有序性這個特征來建立的,我們來看下哪些操作實現了這個特性。可見性可見性是指當一個線程修改了共享變量的值,其他線程能夠立即得知這個修改。 Java內存模型是圍繞著在并發過程中如何處理原子性、可見性和有序性這3個特征來建立的,我們來看下哪些操作實現了這3個特性。 原子性(atomicity): 由Java內存模型來直接保證原子性變量操作包括...
摘要:并發編程關鍵字解析解析概覽內存模型的相關概念并發編程中的三個概念內存模型深入剖析關鍵字使用關鍵字的場景內存模型的相關概念緩存一致性問題。事實上,這個規則是用來保證程序在單線程中執行結果的正確性,但無法保證程序在多線程中執行的正確性。 Java并發編程:volatile關鍵字解析 1、解析概覽 內存模型的相關概念 并發編程中的三個概念 Java內存模型 深入剖析volatile關鍵字 ...
閱讀 3098·2021-11-22 09:34
閱讀 601·2021-11-22 09:34
閱讀 2447·2021-10-08 10:18
閱讀 3384·2021-09-22 15:57
閱讀 2595·2021-09-22 15:25
閱讀 2412·2019-08-30 15:54
閱讀 2120·2019-08-30 15:44
閱讀 1805·2019-08-29 11:18