摘要:線(xiàn)程切換帶來(lái)的原子性問(wèn)題我們把一個(gè)或者多個(gè)操作在執(zhí)行的過(guò)程中不被中斷的特性稱(chēng)為原子性。編譯優(yōu)化帶來(lái)的有序性問(wèn)題顧名思義,有序性指的是程序按照代碼的先后順序執(zhí)行。
緩存導(dǎo)致的可見(jiàn)性問(wèn)題
一個(gè)線(xiàn)程對(duì)共享變量的修改,另外一個(gè)線(xiàn)程能夠立刻看到,稱(chēng)為可見(jiàn)性
在多核下,多個(gè)線(xiàn)程同時(shí)修改一個(gè)共享變量時(shí),如++操作,每個(gè)線(xiàn)程操作的CPU緩存寫(xiě)入內(nèi)存的時(shí)機(jī)是不確定的。除非你調(diào)用CPU相關(guān)指令強(qiáng)刷。
線(xiàn)程切換帶來(lái)的原子性問(wèn)題我們把一個(gè)或者多個(gè)操作在CPU執(zhí)行的過(guò)程中不被中斷的特性稱(chēng)為原子性。
高級(jí)語(yǔ)言里一條語(yǔ)句往往需要多條CPU指令完成。例如count += 1,至少需要三條CPU指令:
指令1:首先,需要把變量count從內(nèi)存加載到CPU的寄存器;
指令2:之后,在寄存器中執(zhí)行+1操作;
指令3:最后,將結(jié)果寫(xiě)入內(nèi)存(緩存機(jī)制導(dǎo)致可能寫(xiě)入的是CPU緩存而不是內(nèi)存)。
操作系統(tǒng)做任務(wù)切換,可以發(fā)生在任何一條CPU指令執(zhí)行完,而不是高級(jí)語(yǔ)言里的一條語(yǔ)句。
編譯優(yōu)化帶來(lái)的有序性問(wèn)題顧名思義,有序性指的是程序按照代碼的先后順序執(zhí)行。
public class Singleton { static Singleton instance; static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) instance = new Singleton(); } } return instance; } }
在new操作上,我們以為 的new操作應(yīng)該是:
分配一塊內(nèi)存M;
在內(nèi)存M上初始化Singleton對(duì)象;
然后M的地址賦值給instance變量。
但是實(shí)際上優(yōu)化后的執(zhí)行路徑卻是這樣的:
分配一塊內(nèi)存M;
將M的地址賦值給instance變量;
最后在內(nèi)存M上初始化Singleton對(duì)象。
優(yōu)化后會(huì)導(dǎo)致什么問(wèn)題呢?我們假設(shè)線(xiàn)程A先執(zhí)行g(shù)etInstance()方法,當(dāng)執(zhí)行完指令2時(shí)恰好發(fā)生了線(xiàn)程切換,切換到了線(xiàn)程B 上;如果此時(shí)線(xiàn)程B也執(zhí)行g(shù)etInstance()方法,那么線(xiàn)程B在執(zhí)行第一個(gè)判斷時(shí)會(huì)發(fā)現(xiàn) instance != null ,所以直接返回 instance,而此時(shí)的instance是沒(méi)有初始化過(guò)的,如果我們這個(gè)時(shí)候訪問(wèn) instance 的成員變量就可能觸發(fā)空指針異常。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74998.html
摘要:有可能一個(gè)線(xiàn)程中的動(dòng)作相對(duì)于另一個(gè)線(xiàn)程出現(xiàn)亂序。當(dāng)實(shí)際輸出取決于線(xiàn)程交錯(cuò)的結(jié)果時(shí),這種情況被稱(chēng)為競(jìng)爭(zhēng)條件。這里的問(wèn)題在于代碼塊不是原子性的,而且實(shí)例的變化對(duì)別的線(xiàn)程不可見(jiàn)。這種不能同時(shí)在多個(gè)線(xiàn)程上執(zhí)行的部分被稱(chēng)為關(guān)鍵部分。 為什么要額外寫(xiě)一篇文章來(lái)研究volatile呢?是因?yàn)檫@可能是并發(fā)中最令人困惑以及最被誤解的結(jié)構(gòu)。我看過(guò)不少解釋volatile的博客,但是大多數(shù)要么不完整,要么難...
摘要:因?yàn)楣芾砣藛T是了解手下的人員以及自己負(fù)責(zé)的事情的。處理器優(yōu)化和指令重排上面提到在在和主存之間增加緩存,在多線(xiàn)程場(chǎng)景下會(huì)存在緩存一致性問(wèn)題。有沒(méi)有發(fā)現(xiàn),緩存一致性問(wèn)題其實(shí)就是可見(jiàn)性問(wèn)題。 網(wǎng)上有很多關(guān)于Java內(nèi)存模型的文章,在《深入理解Java虛擬機(jī)》和《Java并發(fā)編程的藝術(shù)》等書(shū)中也都有關(guān)于這個(gè)知識(shí)點(diǎn)的介紹。但是,很多人讀完之后還是搞不清楚,甚至有的人說(shuō)自己更懵了。本文,就來(lái)整體的...
摘要:因?yàn)楣芾砣藛T是了解手下的人員以及自己負(fù)責(zé)的事情的。處理器優(yōu)化和指令重排上面提到在在和主存之間增加緩存,在多線(xiàn)程場(chǎng)景下會(huì)存在緩存一致性問(wèn)題。有沒(méi)有發(fā)現(xiàn),緩存一致性問(wèn)題其實(shí)就是可見(jiàn)性問(wèn)題。 網(wǎng)上有很多關(guān)于Java內(nèi)存模型的文章,在《深入理解Java虛擬機(jī)》和《Java并發(fā)編程的藝術(shù)》等書(shū)中也都有關(guān)于這個(gè)知識(shí)點(diǎn)的介紹。但是,很多人讀完之后還是搞不清楚,甚至有的人說(shuō)自己更懵了。本文,就來(lái)整體的...
摘要:內(nèi)存模型是圍繞著在并發(fā)過(guò)程中如何處理原子性可見(jiàn)性和有序性這個(gè)特征來(lái)建立的,我們來(lái)看下哪些操作實(shí)現(xiàn)了這個(gè)特性??梢?jiàn)性可見(jiàn)性是指當(dāng)一個(gè)線(xiàn)程修改了共享變量的值,其他線(xiàn)程能夠立即得知這個(gè)修改。 Java內(nèi)存模型是圍繞著在并發(fā)過(guò)程中如何處理原子性、可見(jiàn)性和有序性這3個(gè)特征來(lái)建立的,我們來(lái)看下哪些操作實(shí)現(xiàn)了這3個(gè)特性。 原子性(atomicity): 由Java內(nèi)存模型來(lái)直接保證原子性變量操作包括...
閱讀 2365·2021-11-16 11:52
閱讀 2338·2021-11-11 16:55
閱讀 765·2021-09-02 15:41
閱讀 2997·2019-08-30 15:54
閱讀 3156·2019-08-30 15:54
閱讀 2265·2019-08-29 15:39
閱讀 1520·2019-08-29 15:18
閱讀 981·2019-08-29 13:00