午夜剧场伦理_日本一道高清_国产又黄又硬_91黄色网战_女同久久另类69精品国产_妹妹的朋友在线

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java并發(fā)編程——volatile關(guān)鍵字

瀏覽:20日期:2022-08-23 09:49:56

一、volatile是什么

volatile是Java并發(fā)編程中重要的一個(gè)關(guān)鍵字,被比喻為“輕量級(jí)的synchronized”,與synchronized不同的是,volatile只能修飾變量,無(wú)法修飾方法及代碼塊等。下面是使用volatile關(guān)鍵字實(shí)現(xiàn)的單例模式:

public class Singleton implements Serializable { private static volatile Singleton singleton; private Singleton() {} public static Singleton getSingleton() { if (singleton==null) { // 1 synchronized (Singleton.class) { // 2if (singleton==null) { // 3 singleton = new Singleton();// 4} } } return singleton; } private Object readResolve() { //防止序列化破壞單例模式 return singleton; }}

1.單例為什么使用volatile關(guān)鍵字?

首先要理解new Singleton()做了什么。1.看class對(duì)象是否加載,如果沒(méi)有就進(jìn)行類(lèi)的加載、解析和初始化;2.虛擬機(jī)分配內(nèi)存空間,初始化實(shí)例,3.調(diào)用構(gòu)造函數(shù),4.返回地址給引用。而cpu為了優(yōu)化程序,可能會(huì)進(jìn)行指令重排序,導(dǎo)致實(shí)例內(nèi)存還沒(méi)分配,就被使用了。

假設(shè)有兩個(gè)線程A和B,線程A執(zhí)行到new Singleton(),開(kāi)始初始化實(shí)例對(duì)象,由于存在指令重排序,這次new操作,先把引用賦值了,還沒(méi)有執(zhí)行構(gòu)造函數(shù)(沒(méi)有真正執(zhí)行完)。這時(shí)時(shí)間片結(jié)束了,切換到線程B執(zhí)行,線程B調(diào)用new Singleton()方法,發(fā)現(xiàn)引用不等于null,就直接返回引用地址了,然后線程B執(zhí)行了一些操作,就可能導(dǎo)致線程B使用了還沒(méi)被初始化的變量。

2.單例模式中步驟1、2、3、4存在的意義何在?

首先,步驟2、3是保證單例。假設(shè)線程A和B都執(zhí)行到了步驟2,線程A拿到了鎖,執(zhí)行步驟3,如果此時(shí)沒(méi)有創(chuàng)建實(shí)例,線程A會(huì)執(zhí)行new創(chuàng)建實(shí)例,然后線程A釋放鎖,線程B拿到鎖,首先執(zhí)行步驟3,發(fā)現(xiàn)已經(jīng)創(chuàng)建了實(shí)例,直接返回。加鎖是比較消耗資源的,步驟1就是為了減少資源的消耗。

二、volatile的特性

1.禁止指令重排序

指令重排序是JVM為了優(yōu)化指令、提高程序運(yùn)行效率,在不影響單線程程序執(zhí)行結(jié)果的前提下,盡可能地提高并行度。指令重排序包括編譯器重排序和運(yùn)行時(shí)重排序。

volatile關(guān)鍵字提供內(nèi)存屏障的方式來(lái)防止指令被重排,編譯器在生成字節(jié)碼文件時(shí),會(huì)在指令序列中插入內(nèi)存屏障來(lái)禁止特定類(lèi)型的處理器重排序。

JVM內(nèi)存屏障插入策略:

每個(gè)volatile寫(xiě)操作的前面插入一個(gè)StoreStore屏障,Store1;StoreStore;Store2,在Store2及后續(xù)的寫(xiě)入操作執(zhí)行前,保證Store1的寫(xiě)入操作對(duì)其他處理器可見(jiàn),保證了有序性和可見(jiàn)性; 在每個(gè)volatile寫(xiě)操作的后面插入一個(gè)StoreLoad屏障,Store1;StoreLoad;Load2,在Load2及后續(xù)的讀取操作執(zhí)行前,保證Store1的寫(xiě)入操作對(duì)其他處理器可見(jiàn),它的開(kāi)銷(xiāo)是最大的,兼具其他三種的作用,保證了有序性和可見(jiàn)性; 在每個(gè)volatile讀操作的后面插入一個(gè)LoadLoad屏障,Load1;LoadLoad;Load2,在Load2及后續(xù)的讀取操作執(zhí)行前,保證Load1讀取的數(shù)據(jù)已經(jīng)讀取完畢; 在每個(gè)volatile讀操作的后面插入一個(gè)LoadStore屏障,Load1;LoadStore;Store2,在Store2及后續(xù)的寫(xiě)入操作執(zhí)行前,保證Load1讀取的數(shù)據(jù)已經(jīng)讀取完畢。

2.保證內(nèi)存可見(jiàn)性

可見(jiàn)性是指對(duì)volatile變量的讀總能獲取其他任意線程對(duì)volatile變量的最后的寫(xiě)??梢?jiàn)性的實(shí)現(xiàn)基于volatile讀寫(xiě)的內(nèi)存語(yǔ)義:

volatile寫(xiě)的內(nèi)存語(yǔ)義:當(dāng)寫(xiě)入一個(gè)volatile變量時(shí),JVM將線程工作內(nèi)存中的變量值刷新到主內(nèi)存中; volatile讀的內(nèi)存語(yǔ)義:當(dāng)讀取一個(gè)volatile變量時(shí),JVM首先將改工作內(nèi)存中的變量設(shè)置為無(wú)效,重新從主內(nèi)存中獲取最新的有效值。

三、使用場(chǎng)景

(1)volatile是輕量級(jí)同步機(jī)制。與synchronized的區(qū)別是volatile只能保證有序性和可見(jiàn)性,不能保證原子性。(2)volatile不能修飾寫(xiě)入操作依賴當(dāng)前值的變量。聲明為volatile的簡(jiǎn)單變量如果當(dāng)前值與該變量以前的值相關(guān),那么volatile關(guān)鍵字不起作用,也就是說(shuō)如下的表達(dá)式都不是原子操作:“count++”、“count = count+1”。(3)當(dāng)要訪問(wèn)的變量已在synchronized代碼塊中,或?yàn)槌A繒r(shí),沒(méi)必要使用volatile;(4)volatile保證了有序性,屏蔽掉了JVM中必要的代碼優(yōu)化,所以在效率上比較低,因此一定在必要時(shí)才使用此關(guān)鍵字。(5)在以下兩個(gè)場(chǎng)景中可以使用volatile來(lái)代替synchronized:

運(yùn)算結(jié)果不依賴變量的當(dāng)前值,或者能夠確保只有單一的線程會(huì)修改變量的值。 變量不需要與其他狀態(tài)變量共同參與不變約束。

以上就是淺析Java并發(fā)編程——volatile關(guān)鍵字的詳細(xì)內(nèi)容,更多關(guān)于Java并發(fā)編程——volatile關(guān)鍵字的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 男人的天堂欧美 | 久久久88 | 亚洲激情视频 | 免费成人黄色网址 | 六月婷婷色 | 久久精品黄色 | 久久人人爽人人爽人人片 | 91亚洲国产| 日本黄色大片网站 | 国产免费黄| 色婷婷小说| 一级片日韩 | 美女福利视频在线观看 | 男人的天堂黄色 | 色吧av| 性色av免费 | 亚洲午夜一区 | 亚洲高清不卡 | 亚洲天堂一区在线观看 | 日本黄色动态图 | 日韩一区二区三区免费观看 | 久久精品操 | 欧美性猛交xxxx乱大交 | 亚洲一区二区视频 | 亚洲国产成人自拍 | 麻豆精品网站 | 午夜啊啊啊 | 成人激情视频在线观看 | 一区二区三区在线免费 | 国产精品影院在线观看 | 国产一区二区三区欧美 | 精品国产三级 | 免费福利视频在线观看 | 国产精品乱码久久久 | 婷婷综合五月 | 欧美日韩一区二区三区四区五区 | 成人在线h | 日本精品三区 | 国产午夜久久 | 香蕉色综合 | 男人的午夜天堂 |