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
翻译 孙文强优化