一、Java 中如何保證底層操作的有序性和可見性?
1.解決方案:內存屏障。
2.有序性:內存屏障是可以插入到兩個CPU指令之間的一種指令,用來禁止處理器指令發生重排序,從而保障 有序性(確保指令的執行順序與代碼中的順序一致)。
3.可見性:爲了達到屏障的效果,內存屏障也會使處理器寫入、讀取值之前,將主內存的值寫入高速緩存,清空無效隊列,從而保障 可見性。
4.實現:
1)在Java中,內存屏障可以通過硬件或者軟件實現。
在硬件層面,CPU會提供一些專門的指令來實現內存屏障。
在軟件層面,例如使用sun.misc.Unsafe類中的loadFence和storeFence方法。
Java中的volatile和synchronized關鍵字會使用內存屏障來保證內存操作的有序性和可見性。
2)在C/C++中,編譯器指令如volatile、__sync_synchronize()以及特定處理器的內存屏障指令(如x86的mfence)可以用來實現內存屏障。
5.內存屏障能保證有序性和可見性,但不能保證原子性。
二、volatile內存屏障插入策略:
在Java內存模型(Java Memory Model即JMM)中,內存屏障是通過插入特定的JVM指令實現的。
1.在每個volatile寫操作的前面插入一個StoreStore屏障。
2.在每個volatile寫操作的後面插入一個StoreLoad屏障。
3.在每個volatile讀操作的前面插入一個LoadLoad屏障。
4.在每個volatile讀操作的後面插入一個LoadStore屏障。
三、StoreLoad 屏障:
對于這樣的僞代碼語句 Store1; StoreLoad; Load2,在 Load2 及後續所有讀取操作執行前,保證 Store1 的寫入對所有處理器可見。StoreLoad屏障的開銷是四種屏障(其它3種屏障爲LoadLoad、LoadStore、StoreStore)中最大的(沖刷緩沖器,清空無效隊列)。在大多數處理器的實現中,這個屏障是個萬能屏障,兼具其它三種內存屏障的功能。
四、synchronized關鍵字的作用
1.synchronized關鍵字能保證有序性、可見性、原子性。
2.對于 synchronized關鍵字包住的代碼區域,當線程進入到該區域讀取變量信息時,能保證讀到的是主內存中最新的值。這是因爲在同步區內對變量的寫入操作,在離開同步區時就將當前線程內的數據刷新到主內存中,而對數據的讀取也不能從緩存讀取,只能從主內存中讀取,這樣就保證了數據的讀寫有效性。
五、Android中的同步屏障
Android中分發的消息通常都是同步消息,當需要優先處理重要的異步消息時,可以設置同步屏障,使程序只能處理異步消息而不能處理同步消息。
//async爲true時Handler發送的是異步消息
public Handler(boolean async)
//async爲true時將消息設置爲異步消息
Message.setAsynchronous(boolean async)
微風不燥,陽光正好,你就像風一樣經過這裏,願你停留的片刻溫暖舒心。
我是程序員小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等編程技術的技巧經驗分享),若作品對您有幫助,請關注、分享、點贊、收藏、在看、喜歡,您的支持是我們爲您提供幫助的最大動力。
歡迎關注。助您在編程路上越走越好!