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