av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

面試官:有了解過(guò)Volatile關(guān)鍵字嗎說(shuō)說(shuō)看

概念回顧

首先我們回顧一下之前講的基本概念:

讓客戶(hù)滿意是我們工作的目標(biāo),不斷超越客戶(hù)的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶(hù),將通過(guò)不懈努力成為客戶(hù)在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國(guó)際域名空間、網(wǎng)頁(yè)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、興平網(wǎng)站維護(hù)、網(wǎng)站推廣。

內(nèi)存可見(jiàn)性

「內(nèi)存可見(jiàn)性,指的是線程之間的可見(jiàn)性,當(dāng)一個(gè)線程修改了共享變量時(shí),另一個(gè)線程可以讀取到這個(gè)修改后的值」。

重排序

為優(yōu)化程序性能,對(duì)原有的指令執(zhí)行順序進(jìn)行優(yōu)化重新排序。重排序可能發(fā)生在多個(gè)階段,比如編譯重排序、CPU重排序等。

happens-before

遵循h(huán)appens-before規(guī)則,JVM就能保證指令在多線程之間的順序性符合執(zhí)行的預(yù)期。

volatile

  • 保證變量的「內(nèi)存可見(jiàn)性」。
  • 禁止volatile變量與普通變量「重排序」。

那么這個(gè)內(nèi)存可見(jiàn)性過(guò)程是怎么樣的呢?之前也有給大家演示過(guò)具體代碼,這里直接給大家總結(jié)一下:

所謂內(nèi)存可見(jiàn)性, 當(dāng)一個(gè)線程對(duì)volatile修飾的變量進(jìn)行寫(xiě)操作時(shí),會(huì)立即將本地內(nèi)存中的共享變量刷新到主內(nèi)存, 同理,當(dāng)進(jìn)行讀操作時(shí),會(huì)立即將本地內(nèi)存失效,從主內(nèi)存中讀取共享變量的值。

在這一點(diǎn)上,volatile與鎖具有相同的內(nèi)存效果,volatile變量的寫(xiě)和鎖的釋放具有相同的內(nèi)存語(yǔ)義,volatile變量的讀和鎖的獲取具有相同的內(nèi)存語(yǔ)義。

禁止重排又是怎么回事呢?

在JSR-133之前的舊的Java內(nèi)存模型中,是允許volatile變量與普通變量重排序的。想想看,如果可重排,會(huì)發(fā)生什么?

我們假設(shè)有兩個(gè)線程A和B,一個(gè)被volatile修飾的變量a,一個(gè)未被修飾的普通變量b,看下邊代碼:

volatile a = 1;
int b = 2;
public void writer() {
a = 1;
b = 3;
}
public void reader() {
if (a == 1) {
System.out.println(b);
}
}

線程A執(zhí)行writer方法,首先將a設(shè)置為1,此時(shí)B線程操作reader方法,此時(shí)判斷a=1,然后進(jìn)行輸出b=2,線程A多b操作設(shè)置為3,其實(shí)最終結(jié)果應(yīng)該b=3才對(duì),所以這里重排可能會(huì)導(dǎo)致普通變量讀錯(cuò)的情況。

為了提供一種比鎖更輕量級(jí)的「線程間的通信機(jī)制」,JSR-133決定增強(qiáng)volatile的內(nèi)存語(yǔ)義:嚴(yán)格限制編譯器和處理器對(duì)volatile變量與普通變量的重排序。那么它是怎么禁止的呢答案是通過(guò)內(nèi)存屏障,或許你聽(tīng)說(shuō)過(guò)這個(gè)概念,下面我們一起看一下。

內(nèi)存屏障

什么是內(nèi)存屏障呢?在計(jì)算機(jī)中,主要分為兩種,一種是讀屏障(Load Barrier)和寫(xiě)屏障(Store Barrier)。內(nèi)存屏障有兩個(gè)作用:

  • 阻止屏障兩側(cè)的指令重排序。
  • 強(qiáng)制把寫(xiě)緩沖區(qū)/高速緩存中的臟數(shù)據(jù)等寫(xiě)回主內(nèi)存,或者讓緩存中相應(yīng)的數(shù)據(jù)失效。(這里的緩存指的是cpu的多級(jí)緩存如L1,L2)。

我們寫(xiě)的代碼最終都是要通過(guò)編譯器的,那么編譯器是怎么實(shí)現(xiàn)這個(gè)過(guò)程的呢?

編譯器在生成字節(jié)碼的時(shí)候,會(huì)在指令序列中插入內(nèi)存屏障來(lái)禁止特定類(lèi)型的處理器重排序。在Java中,JMM內(nèi)存屏障插入策略可以保證各平臺(tái)處理器下程序的volatile內(nèi)存語(yǔ)義正確,具體策略:

  • 在每個(gè)volatile寫(xiě)操作前插入一個(gè)寫(xiě)屏障。
  • 在每個(gè)volatile寫(xiě)操作后插入一個(gè)寫(xiě)屏障。
  • 在每個(gè)volatile讀操作后插入一個(gè)讀屏障。
  • 在每個(gè)volatile讀操作后再插入一個(gè)讀屏障。

volatile與普通變量的重排序規(guī)則:

  1. 如果第一個(gè)操作是volatile讀,那無(wú)論第二個(gè)操作是什么,都不能重排序。
  2. 如果第二個(gè)操作是volatile寫(xiě),那無(wú)論第一個(gè)操作是什么,都不能重排序。
  3. 如果第一個(gè)操作是volatile寫(xiě),第二個(gè)操作是volatile讀,那不能重排序。

那么如果第一個(gè)操作是普通變量讀,第二個(gè)是volatile讀,可以重排嗎?

答案: 可以的。

volatile使用場(chǎng)景

相信在了解以上概念之后,對(duì)它應(yīng)該有一定的認(rèn)識(shí)了, volatile可以保證內(nèi)存可見(jiàn)性且禁止重排序, 它跟鎖又具有相同的內(nèi)存語(yǔ)義,又被稱(chēng)為輕量級(jí)鎖。volatile僅僅保證對(duì)單個(gè)volatile變量的讀/寫(xiě)具有原子性,而鎖可以保證整個(gè)「臨界區(qū)代碼」的執(zhí)行具有原子性。所以鎖更高級(jí)一點(diǎn)。但也不是說(shuō)volatile就不好,作為輕量級(jí)的鎖,某些場(chǎng)景下還是非常有用的。

我們以雙重鎖檢查單例模式為例,首先我們看一下普通的單例模式:

class Singleton {
private static Singleton instance;
private Singleton() {}
public Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}

單線程下你可以這么搞,沒(méi)毛病,多線程下就不行了,所有我們要加鎖,于是雙重鎖檢查下的實(shí)現(xiàn):

class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

這樣就真沒(méi)問(wèn)題了嗎疑問(wèn)?我們知道在new的時(shí)候,主要做了三件事:

  • 分配內(nèi)存
  • 變量賦值
  • 初始化對(duì)象

這個(gè)過(guò)程中,可能會(huì)導(dǎo)致指令重排,有可能你會(huì)說(shuō)里邊加鎖了,上節(jié)給大家介紹順序一致性模型中,我們講過(guò),在同步模式下臨界區(qū)內(nèi)的代碼可以發(fā)生重排序,所以這里還是有可能發(fā)生重排序的,所以最終的這個(gè)過(guò)程,可能會(huì)這樣。

線程A執(zhí)行 分配內(nèi)存 -> 變量賦值, 線程B執(zhí)行 判斷 instance不為null 開(kāi)始訪問(wèn)對(duì)象,實(shí)際上對(duì)象還未初始化,所以這時(shí)候,我們就要加上volatile。

class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

這樣在多線程環(huán)境下,可以保證其安全性。

結(jié)束語(yǔ)

本節(jié)內(nèi)容可能不像之前那么好理解,比較抽象,所以本文也有不足的地方,大家自己可以多查查一些資料,綜合理解, 不要去背概念。本節(jié)我們提到了鎖的概念。


分享題目:面試官:有了解過(guò)Volatile關(guān)鍵字嗎說(shuō)說(shuō)看
文章源于:http://uogjgqi.cn/article/codgiho.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流