徹底搞懂Volatile

徹底搞懂Volatile

大家都知道volatile有着三個特性,可見性,非原子性,還有個防止指令重排

可見性指的是一個線程對一個共享變量的修改,另一個變量也能讀到修改的值

volatile比Synchronized的使用成本更低,它不會引起線程的上下文切換和調度

1. Volatile的定義

爲了確保線程對同一共享變量能準確的和一致性的更新。一般情況是通過排他鎖,而volatile更爲方便,能使java線程內存模型確保所有線程對共享變量的一致性

我們先看一下JMM的內存模型,再回來說Volatile

JMM 對程序間變量的訪問做出的規則

先read主內存的變量,再load到工作內存,use取出工作內存的值給執行引擎使用
assign把執行引擎的值賦值給工作內存,store把工作內存的傳遞給主內存,主內存再write寫入

如果不用static變量,那麼多個線程之間共享變量的修改,如何保持可見呢?這就是問題引出了volatile了

接着來說volatile如何保證可見性

其實只要反彙編加了volatile的代碼,都會發現有lock指令

通過查IA-32架構軟件開發者手冊可知

lock前綴指令會在多核處理器下引發兩件事

  1. 將當前處理器緩存行的數據寫回主內存

如果緩存數據已經在工作內存了,它就會鎖定這塊內存區域得緩存,然後寫回主內存,再以緩存一致性爲基礎,保證了其它線程得數據一致,這個操作就叫緩存鎖定它會阻止多個處理器同時修改共享變量

  1. 當一個處理器寫回數據的時候,會使其它cpu緩存的這個數據失效

​ 這個就不難理解了,緩存一致性得作用,通過總線嗅探是否緩存數據內存地址已經發生改變

爲什麼處理器不直接在內存工作,這樣就可以大家不需要緩存了,直接從內存讀取值就像redis一樣

這個想法其實以前就想到了,在很久以前的處理機,他們都有一個總線鎖的機制,在一個處理器修改的時候,會獨佔整個內存和所有相關的數據,其它人期間只能等待,但是這樣效率太低了,全部鎖住,那麼其它人只要需要用到,都得卡住

緩存一致性MESI協議

爲了保證各個處理器上得緩存是一致性得,每個處理器會通過嗅探在總線上傳播得數據來看自己得值是不是被修改了,如果發現內存地址被修改,就會將當前緩存得數據設置爲失效,如果還想操作這個數據,就要重新從內存讀取,這樣就保證了一致性

其實還有一點沒分析,就是volatile得優化,但是本人能力有限日後再補上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章