vloatile總結與synchronized對比

原文地址;https://www.cnblogs.com/xiaoxian1369/p/5411877.htmlhtml

一、要使volatile變量提供理想的線程安全,必須同時知足如下兩個條件:
1)、對變量的寫操做不依賴於當前值;
2)、該變量沒有包含在具備其餘變量的不變式中。數組

第一個條件的限制使volatile變量不能用做線程安全的計數器。雖然增了操做(x++)看上去相似一個單獨操做,實際上它是一個由讀取-修改-寫入操做序列組成的組合操做,必須以原子方式執行,而volatile不能提供必須的原子特性。實現正確的操做須要使x的值在操做期間保持不變,而volatile變量沒法實現這一點。安全


二、通常共享變量是存放中主內存中,每個線程都有一個屬於本身的工做內存;當一個線程開始時,會將變量從主內存中拷貝一份副本放在本身的工做內存中,當使用時就高效多了,當有更改時,會回寫到主內存中;當此時有多個線程對同一個共享變量進行操做時,只會操做屬於本身線程的工做內存,以後回寫到主內存中,相互之間不會有影響,故此時會有多線程安全問題。當該共享變量使用volatile修改時,一個線程對其進行了修改,則其回寫到主內存時,會告知其餘有該共享變量的副本,該副本已經失效了,故其餘線程要使用該共享變量時,就會從新從主內存中拷貝一份副本到本線程中,以確保其線程內使用的都是最新的。多線程

三、通常一個線程對變量的操做須要經歷從主內存中讀取Read--->加載到工做線程中load---->在工做線程中使用use--->該該共享變量進行賦值asign--->對該共享變量進行存儲store--->將該共享變量回寫到主內存中write。線程


四、一個共享變量被volatile修飾以後,就具有兩層含義:
1)、保證不一樣線程對這個變量進行操做時的可見性,即一個線程修改了變量的值,該變量的新值對其餘線程來講是當即可見的,但不保證操做的原子性;
2)、禁止進行指令重排。htm

五、使用synchronized能夠保證變量修改的可見性和原子性,而volatile只能保證變量的可見性;synchronized是重量級的加鎖,且開銷大,而volatile是輕量級的無鎖,且開銷小對象

六、對於volatile修飾的引用類型(包括對象、數組等),其僅僅是保證引用地址的可見性,而不是引用指向的對象中元素的可見性。blog

七、通常64位的long和double是非原子操做的,是使用高低32位來進行賦值的,故這種64位的變量的賦值是非原子操做的,但在現代JVM中,都已保證該賦值操做是原子操做的。排序

八、關於指令重排,是指處理器爲了提升處理速度將一些指令從新排序,但保證最終的結果是一致的,跟重排前的結果同樣,這種是容許的;而volatile能防止指令重排,能夠認爲是在指令中增長了內存屏障,使在該volatile修飾的變量所屬的指令,在沒有使用以前,其前面的指令能夠放在該指令以後,其後面的指令一樣能夠放在該指令以前,但有了該修改,則不會這樣。內存

相關文章
相關標籤/搜索