注意:這是inter X86java
store fence 在sfence指令前面的寫操做必須在sfence指令後邊的寫操做前完成c++
如圖:若是沒有sfence ,是不能保證操做1在操做2執行前就執行完的,有了sfence才能保證操做1和操做2的順序面試
load fence 指令前的讀操做必須在lfence指令後邊的讀操做執行前執行 windows
如圖: 若是沒有lfence 不能保證讀操做1 和 讀操做2 的順序 ,有了lfence就能夠保證了jvm
mix fence 是集合了sfence和lfence的全部做用於一身,mfence前邊的讀寫操做必須在mfence後邊讀寫操做開始以前完成佈局
如圖:mfence能夠保證 在執行讀操做2和寫操做2以前 必須執行完讀操做1和寫操做1
this
除了fence外,還有一些原子指令 ,好比 lock xxx spa
這些原子指令是一個Full Barrier,執行時會鎖住內存子系統來保證執行順序操作系統
甚至跨多個cpucode
注意:jvm這只是jvm的規範,具體實現要看虛擬機怎麼實現
保證讀操做的順序,LoadLoad前邊的讀操做必須在LoadLoad後邊的讀操做前完成
如圖: LoadLoad能保證 讀操做2和者讀操做3執行前 必須執行完讀操做0 和讀操做1
對比LoadLoad 保證寫操做有序
對比LoadLoad 保證讀操做和寫操做有序
對比 LoadLoad 保證寫操做和讀操做有序
這裏用到jclasslib 前邊文章講過怎麼安裝
public class VolatileTest { int i; volatile int x; public static void main(String[] args) { } }
jclasslib 能夠看出來:
i的修飾符是 0x0000[]
x的修飾符是 0x0040[volatile]
很明顯,字節碼層面就只是給加了volatile的屬性加了一個標識
在寫操做 和 讀操做先後加了屏障
先後加了屏障,保證了順序性
volatile類型變量修改以後會當即寫回內存 ,也就是從工做內存寫回到主內存(JMM知識)
須要使用hsdis進行反彙編,也就是把class編譯成彙編指令。深刻理解Java虛擬機(第三版),448頁有個例子,這裏就不敘述了, 其實做爲了解便可 ,底層也是經過sfence lfence mfence 或者 lock 實現的。
windows x86 是用過lock 實現的
這裏須要使用hsdis ,沒有太大必要去使用 ,若是有興趣能夠用一下,不是很難,之後有時間寫一篇簡單應用的文章。
public class TestSync { synchronized void m(){ } void n(){ synchronized (this){ } } }
一樣使用jclasslib看
能夠看出來 方法是用了一個標識符, 代碼塊使用了monitorenter monitorexit 語句
c、c++調用操做系統提供的同步機制
x86:使用的lock cmpxchg 等 指令
只是做爲了解,其實工做中不多能用到,感興趣的能夠根據具體的關鍵字進行查詢
按照字節碼、jvm、操做系統硬件層面 這三個層面理解便可
最後寫一個面試題你們看看能回答上來嗎?
下一篇以這個題爲例 寫一篇文章
有問題歡迎留言,也可公衆號 留言(響應快):