AtomicLong.lazySet 是如何工做的?

Quora上有人提問AtomicLong.lazySet如何工做的?html

Jackson Davis答道:java

爲一個AtomicLong對象設置一個值,jvm會確保其餘線程讀取到最新值,原子類和voliatile變量也是同樣的,這是由依賴於硬件的系統指令(如x86的xchg)實現的。lazySet倒是沒法保證這一點的方法,因此其餘線程在以後的一小段時間裏仍是能夠讀到舊的值。這有什麼好處呢?性能:在多核處理器下,內存以及cpu緩存的讀和寫經常是順序執行的,因此在多個cpu緩存之間同步一個內存值的代價是很昂貴的。linux

如何實現呢?大多數的原子類,好比AtomicLong本質上都是一個Unsafe和一個volatile Long變量的包裝類。值得注意的是AtomicLong.lazySet方法實際是調用了本地方法Unsafe.putOrderedLong,本地方法Unsafe.putOrderedLong的實現能夠參考http://hg.openjdk.java.net/jdk7/…。從Unsafe的代碼中能夠發現Unsafe_setOrderedLong是一個本地方法(c++實現),它僅調用了SET_FIELD_VOLATILE,這非常奇怪,咱們指望共享的Unsafe_setLongVolatile擁有不一樣的語義。PS:在非加強版本中,setOrdered僅僅是調用了setVolatile方法,非常讓人失望。深刻查看你會發現其實他們是相同的,SET_FIELD_VOLATILE是一個OrderAccess:release_store_fence的包裝。能夠在Linux x86的代碼http://hg.openjdk.java.net/jdk7/…中找到此方法的實現,在64bit x86系統中採用xchgq來代碼,64位版本指令的問題我上面有提到過,上火。c++

ps:從理論上講lazySet能比一個標準的volatile變量的寫性能更好。可是我在openJdk裏沒有找到相關代碼。緩存

Felix Sulima補充道:jvm

sun.misc.unsafe不少方法被jvm加強了,JIT(just in time運行時編譯執行的技術)直接解釋而忽略原始的實現。能夠在這裏找到這個例子:src/share/vm/classfile/vmSymbols.hpp@3facbb14e873列表中的native方法僅僅是非JIT環境下的一個備份的內部方法。例如,若是它沒有被調用(我也不知道是什麼緣由),所以這些方法缺少一些必要的優化。從Talk from JAX London的幻燈片11-12能夠看到AtomicLong.lazySet(…)在x86系統上會被編譯成「mov」指令。這裏是Google Group裏關於如何得到JIT裝配的一個描述。性能


原文 How-does-AtomicLong-lazySet-work
翻譯 孫文強優化

相關文章
相關標籤/搜索