成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java并發(fā)編程-volatile可見性的介紹

YJNldm / 3106人閱讀

摘要:如何擁有可見性先介紹一下內(nèi)存模型中定義的種工作內(nèi)存與主內(nèi)存之間的原子操作鎖定作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)識(shí)為一條線程獨(dú)占的狀態(tài)。并沒(méi)有達(dá)到期望的。

前言

要學(xué)習(xí)好Java的多線程,就一定得對(duì)volatile關(guān)鍵字的作用機(jī)制了熟于胸。最近博主看了大量關(guān)于volatile的相關(guān)博客,對(duì)其有了一點(diǎn)初步的理解和認(rèn)識(shí),下面通過(guò)自己的話敘述整理一遍。

有什么用?

volatile主要對(duì)所修飾的變量提供兩個(gè)功能

可見性

防止指令重排序


本篇博客主要對(duì)volatile可見性進(jìn)行探討,以后發(fā)表關(guān)于指令重排序的博文。

什么是可見性?

一圖勝千言

上圖已經(jīng)把JAVA內(nèi)存模型(JMM)展示得很詳細(xì)了,簡(jiǎn)單概括一下

每個(gè)Thread有一個(gè)屬于自己的工作內(nèi)存(可以理解為每個(gè)廚師有一個(gè)屬于自己的鐵鍋)

所有Thread共用一個(gè)主內(nèi)存(餐廳所有的廚師共用同一個(gè)冰箱)

每個(gè)Thread操作數(shù)據(jù)之前都會(huì)去主內(nèi)存中獲取數(shù)據(jù)(廚師炒菜之前都要去冰箱里拿食材)

Thread:廚師

工作內(nèi)存:鐵鍋

store&load:放熟食,取食材

主內(nèi)存:冰箱

讀者可思考以下情景:

餐廳來(lái)了一位顧客點(diǎn)了一份紅燒肉,此時(shí)有兩位大廚(假設(shè)大廚之間互不通信),由于互不通信,所以兩位大廚都打開冰箱取出食材開始炒菜。
最后炒出了兩份紅燒肉,顧客只要一份。為什么會(huì)造成這種結(jié)果?

由于大廚之間沒(méi)有可見性。

將此情景放在JAVA中即是:

線程A從主內(nèi)存中取了一個(gè)變量到工作內(nèi)存中,操作完畢后沒(méi)有及時(shí)放回主內(nèi)存中,于是線程B去取這個(gè)變量已經(jīng)過(guò)期了,取的是線程A操作之前的變量。

如何擁有可見性?

先介紹一下Java內(nèi)存模型中定義的8種工作內(nèi)存與主內(nèi)存之間的原子操作

lock( 鎖定 ):作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)識(shí)為一條線程獨(dú)占的狀態(tài)。

unlock(解鎖):作用于主內(nèi)存的變量,把一個(gè)處于鎖定的變量釋放出來(lái),釋放變量才可以被其他線程鎖定。

read(讀取):作用于主內(nèi)存的變量,把一個(gè)變量的值從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的load動(dòng)作使用。

load(載入):作用于工作內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中。

use(使用):作用于工作內(nèi)存種的變量,它把工作內(nèi)存中一個(gè)變量的值傳遞給執(zhí)行引擎,每當(dāng)虛擬機(jī)遇到一個(gè)需要使用到變量的值的字節(jié)碼指令時(shí)將會(huì)執(zhí)行這個(gè)操作。

assign(賦值):作用于工作內(nèi)存中的變量,它把一個(gè)從執(zhí)行引擎接收到的值賦給工作內(nèi)存的變量,每當(dāng)虛擬機(jī)遇到一個(gè)給變量賦值的字節(jié)碼指令時(shí)執(zhí)行這個(gè)操作。

store(存儲(chǔ)):作用于工作內(nèi)存的變量,它把工作內(nèi)存中一個(gè)變量的值傳送到主內(nèi)存中,以便隨后的write操作使用

write(寫入):作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中得到的值放入主內(nèi)存的變量中。

讀取賦值一個(gè)普通變量的情況


當(dāng)線程1對(duì)主內(nèi)存對(duì)象發(fā)起read操作到write操作套流程的時(shí)間里,線程2隨時(shí)都有可能對(duì)這個(gè)主內(nèi)存對(duì)象發(fā)起第二套操作

有什么危害呢?

假設(shè)主內(nèi)存中有一個(gè)

int a=0;

線程1和線程2分別執(zhí)行一次,理想狀態(tài)下最終a的值為2.

a++;

線程1在執(zhí)行了assign操作之后變量a的真實(shí)值已經(jīng)從0變成了1,但是這個(gè)過(guò)程發(fā)生在工作內(nèi)存中對(duì)其他線程不可見,若線程2此時(shí)對(duì)變量a的操作,讀取到的值仍然為0,因?yàn)闆](méi)有可見性,線程2的操作也僅僅是重復(fù)了線程1的操作,再次讓a從0變成了1。并沒(méi)有達(dá)到期望的a=2。

讀取賦值一個(gè)volatile變量的情況


volatile變量對(duì)對(duì)象的操作更嚴(yán)格:

use之前不能被read&load

assign之后必須緊跟store&write

也就是說(shuō) read-load-useassign-store-write成為了兩個(gè)不可分割的原子操作

盡管這時(shí)候在use和assign之間依然有一段真空期,有可能變量會(huì)被其他線程讀取,但是無(wú)論在哪一個(gè)時(shí)間點(diǎn)主內(nèi)存的變量和任一工作內(nèi)存的變量的值都是相等的。這個(gè)特性就導(dǎo)致了volatile變量不適合參與到依賴當(dāng)前值的運(yùn)算,如自增。
那么依靠可見性的特點(diǎn)volatile可以用在哪些地方呢?
《Java虛擬機(jī)》提到:

運(yùn)算結(jié)果并不依賴變量的當(dāng)前值(即結(jié)果對(duì)產(chǎn)生中間結(jié)果不依賴),或者能夠確保只有單一的線程修改變量的值

通常volatile用做保存某個(gè)狀態(tài)的boolean值。

部分參考自

volatile變量與普通變量的區(qū)別

<<深入理解Java虛擬機(jī) 高級(jí)特性與最佳實(shí)踐>>

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69423.html

相關(guān)文章

  • 并發(fā)編程的藝術(shù)

    摘要:假設(shè)不發(fā)生編譯器重排和指令重排,線程修改了的值,但是修改以后,的值可能還沒(méi)有寫回到主存中,那么線程得到就是很自然的事了。同理,線程對(duì)于的賦值操作也可能沒(méi)有及時(shí)刷新到主存中。線程的最后操作與線程發(fā)現(xiàn)線程已經(jīng)結(jié)束同步。 很久沒(méi)更新文章了,對(duì)隔三差五過(guò)來(lái)刷更新的讀者說(shuō)聲抱歉。 關(guān)于 Java 并發(fā)也算是寫了好幾篇文章了,本文將介紹一些比較基礎(chǔ)的內(nèi)容,注意,閱讀本文需要一定的并發(fā)基礎(chǔ)。 本文的...

    curlyCheng 評(píng)論0 收藏0
  • 多線程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線程事半功倍

    摘要:是需要我們?nèi)ヌ幚砗芏嗍虑?,為了防止多線程給我們帶來(lái)的安全和性能的問(wèn)題下面就來(lái)簡(jiǎn)單總結(jié)一下我們需要哪些知識(shí)點(diǎn)來(lái)解決多線程遇到的問(wèn)題。 前言 不小心就鴿了幾天沒(méi)有更新了,這個(gè)星期回家咯。在學(xué)校的日子要努力一點(diǎn)才行! 只有光頭才能變強(qiáng) 回顧前面: 多線程三分鐘就可以入個(gè)門了! Thread源碼剖析 本文章的知識(shí)主要參考《Java并發(fā)編程實(shí)戰(zhàn)》這本書的前4章,這本書的前4章都是講解并發(fā)的基...

    YPHP 評(píng)論0 收藏0
  • 淺談Java并發(fā)編程系列(四)—— 原子性、可見性與有序性

    摘要:內(nèi)存模型是圍繞著在并發(fā)過(guò)程中如何處理原子性可見性和有序性這個(gè)特征來(lái)建立的,我們來(lái)看下哪些操作實(shí)現(xiàn)了這個(gè)特性??梢娦钥梢娦允侵府?dāng)一個(gè)線程修改了共享變量的值,其他線程能夠立即得知這個(gè)修改。 Java內(nèi)存模型是圍繞著在并發(fā)過(guò)程中如何處理原子性、可見性和有序性這3個(gè)特征來(lái)建立的,我們來(lái)看下哪些操作實(shí)現(xiàn)了這3個(gè)特性。 原子性(atomicity): 由Java內(nèi)存模型來(lái)直接保證原子性變量操作包括...

    tianren124 評(píng)論0 收藏0
  • 手撕面試官系列(七):面試必備之常問(wèn)并發(fā)編程高級(jí)面試專題

    摘要:如何在線程池中提交線程內(nèi)存模型相關(guān)問(wèn)題什么是的內(nèi)存模型,中各個(gè)線程是怎么彼此看到對(duì)方的變量的請(qǐng)談?wù)動(dòng)惺裁刺攸c(diǎn),為什么它能保證變量對(duì)所有線程的可見性既然能夠保證線程間的變量可見性,是不是就意味著基于變量的運(yùn)算就是并發(fā)安全的請(qǐng)對(duì)比下對(duì)比的異同。 并發(fā)編程高級(jí)面試面試題 showImg(https://upload-images.jianshu.io/upload_images/133416...

    Charles 評(píng)論0 收藏0
  • 貓頭鷹的深夜翻譯:Volatile的原子性, 可見性和有序性

    摘要:有可能一個(gè)線程中的動(dòng)作相對(duì)于另一個(gè)線程出現(xiàn)亂序。當(dāng)實(shí)際輸出取決于線程交錯(cuò)的結(jié)果時(shí),這種情況被稱為競(jìng)爭(zhēng)條件。這里的問(wèn)題在于代碼塊不是原子性的,而且實(shí)例的變化對(duì)別的線程不可見。這種不能同時(shí)在多個(gè)線程上執(zhí)行的部分被稱為關(guān)鍵部分。 為什么要額外寫一篇文章來(lái)研究volatile呢?是因?yàn)檫@可能是并發(fā)中最令人困惑以及最被誤解的結(jié)構(gòu)。我看過(guò)不少解釋volatile的博客,但是大多數(shù)要么不完整,要么難...

    Lionad-Morotar 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<