久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

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

Java volatile如何實(shí)現(xiàn)禁止指令重排

瀏覽:19日期:2022-08-21 15:14:33

計(jì)算機(jī)在執(zhí)行程序時(shí),為了提高性能,編譯器和處理器常常會對指令重排,一般分為以下三種:

源代碼 -> 編譯器優(yōu)化的重排 -> 指令并行的重排 -> 內(nèi)存系統(tǒng)的重排 -> 最終執(zhí)行指令

單線程環(huán)境里面確保最終執(zhí)行結(jié)果和代碼順序的結(jié)果一致

處理器在進(jìn)行重排序時(shí),必須要考慮指令之間的數(shù)據(jù)依賴性

多線程環(huán)境中線程交替執(zhí)行,由于編譯器優(yōu)化重排的存在,兩個(gè)線程中使用的變量能否保證一致性是無法確定的,結(jié)果無法預(yù)測。

指令重排 - example 1

public void mySort() {int x = 11;int y = 12;x = x + 5;y = x * x;}

按照正常單線程環(huán)境,執(zhí)行順序是 1 2 3 4

但是在多線程環(huán)境下,可能出現(xiàn)以下的順序:

2 1 3 4

1 3 2 4

上述的過程就可以當(dāng)做是指令的重排,即內(nèi)部執(zhí)行順序,和我們的代碼順序不一樣

但是指令重排也是有限制的,即不會出現(xiàn)下面的順序

4 3 2 1

因?yàn)樘幚砥髟谶M(jìn)行重排時(shí)候,必須考慮到指令之間的數(shù)據(jù)依賴性

因?yàn)椴襟E 4:需要依賴于 y的申明,以及x的申明,故因?yàn)榇嬖跀?shù)據(jù)依賴,無法首先執(zhí)行

例子

int a,b,x,y = 0

線程1 線程2 x = a; y = b; b = 1; a = 2; x = 0; y = 0

因?yàn)樯厦娴拇a,不存在數(shù)據(jù)的依賴性,因此編譯器可能對數(shù)據(jù)進(jìn)行重排

線程1 線程2 b = 1; a = 2; x = a; y = b; x = 2; y = 1

這樣造成的結(jié)果,和最開始的就不一致了,這就是導(dǎo)致重排后,結(jié)果和最開始的不一樣,因此為了防止這種結(jié)果出現(xiàn),volatile就規(guī)定禁止指令重排,為了保證數(shù)據(jù)的一致性

指令重排 - example 2

比如下面這段代碼

public class ResortSeqDemo { int a= 0; boolean flag = false; public void method01() { a = 1; flag = true; } public void method02() { if(flag) { a = a + 5; System.out.println('reValue:' + a); } }}

我們按照正常的順序,分別調(diào)用method01() 和 method02() 那么,最終輸出就是 a = 6

但是如果在多線程環(huán)境下,因?yàn)榉椒? 和 方法2,他們之間不能存在數(shù)據(jù)依賴的問題,因此原先的順序可能是

a = 1;flag = true;

a = a + 5;System.out.println('reValue:' + a);

但是在經(jīng)過編譯器,指令,或者內(nèi)存的重排后,可能會出現(xiàn)這樣的情況

flag = true;

a = a + 5;System.out.println('reValue:' + a);

a = 1;

也就是先執(zhí)行 flag = true后,另外一個(gè)線程馬上調(diào)用方法2,滿足 flag的判斷,最終讓a + 5,結(jié)果為5,這樣同樣出現(xiàn)了數(shù)據(jù)不一致的問題

為什么會出現(xiàn)這個(gè)結(jié)果:多線程環(huán)境中線程交替執(zhí)行,由于編譯器優(yōu)化重排的存在,兩個(gè)線程中使用的變量能否保證一致性是無法確定的,結(jié)果無法預(yù)測。

這樣就需要通過volatile來修飾,來保證線程安全性

Volatile針對指令重排做了啥

Volatile實(shí)現(xiàn)禁止指令重排優(yōu)化,從而避免了多線程環(huán)境下程序出現(xiàn)亂序執(zhí)行的現(xiàn)象

首先了解一個(gè)概念,內(nèi)存屏障(Memory Barrier)又稱內(nèi)存柵欄,是一個(gè)CPU指令,它的作用有兩個(gè):

保證特定操作的順序保證某些變量的內(nèi)存可見性(利用該特性實(shí)現(xiàn)volatile的內(nèi)存可見性)

由于編譯器和處理器都能執(zhí)行指令重排的優(yōu)化,如果在指令鍵插入一條Memory Barrier則會告訴編譯器和CPU,不管什么指令都不能和這條Memory Barrier指令重排序,也就是說,通過插入內(nèi)存屏障前后的指令執(zhí)行重排序優(yōu)化。內(nèi)存屏障另外一個(gè)作用是刷新出各種CPU的緩存數(shù),因此任何cpu上的線程都能讀取到這些數(shù)據(jù)的最新版本

Java volatile如何實(shí)現(xiàn)禁止指令重排

也就是在Volatile的寫和讀的時(shí)候,加入屏障,防止出現(xiàn)指令重排線程安全得到保證

工作內(nèi)存與主內(nèi)存同步延遲現(xiàn)象導(dǎo)致的可見性問題

可以使用synchronized或volatile關(guān)鍵字解決,它們都可以使得一個(gè)線程修改后的變量立即對其他線程可見。 對于指令重排導(dǎo)致的可見性問題和有序性問題 可以利用volatile關(guān)鍵字解決,因?yàn)関olatile的另一個(gè)作用就是禁止重排序優(yōu)化。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 成人高清在线 | 欧美在线一区二区三区 | 久久久成人精品 | 99久久精品国产一区二区三区 | 国产精品九九九 | 91香蕉 | 国产精品久久免费视频 | 亚洲伊人精品酒店 | 精品久久久久久国产 | 国产精品视频久久久 | 黄片毛片在线观看 | aaa久久| 视频一区二区国产 | 色xx综合网| 成人午夜视频在线观看 | 亚洲成人高清在线 | 欧美在线网站 | 国产精品影院在线观看 | 久久亚洲综合 | www午夜| 欧美专区在线 | 亚洲一级黄色 | jizzjizz亚洲中国少妇 | 特级淫片女子高清视频在线观看 | 亚洲精品福利视频 | 欧美午夜精品久久久久久人妖 | 国产精品亚洲第一 | 国产精品永久免费自在线观看 | 亚洲欧洲视频 | 久久精品一 | 日本aa级毛片免费观看 | 欧美精品一区视频 | 亚洲大片一区 | 欧美在线观看视频 | 在线观看一级片 | 黄色永久网站 | 欧美一级精品片在线看 | 一区二区免费视频 | 日本高清视频一区二区三区 | 久草热8精品视频在线观看 欧美全黄 | 欧美一区二区三区免费 |