我一直在阅读关于Compare and Swap(CAS)如何在幕后工作的网络文章,因为AtomicInteger、AtomicLong和其他原子变量都使用JNI的“Unsafe”库的compareAndSet()方法,但当你进入实际实现时,你会得到一个空白的、抽象的方法,它没有告诉你compareAndSet()实际上是如何线程安全的。
@HotSpotIntrinsicCandidate
public final native boolean compareAndSetLong(Object o, long offset,
long expected,
long x);
有人想知道JNI的Unsafe库如何保证原子变量的线程安全性吗?
2条答案
按热度按时间fae0ux8s1#
注意JNI和Unsafe是不相关的:Unsafe不是JNI的一部分,正如已经指出的,尽管有本机方法,但Unsafe不是用JNI实现的。
它在VM中直接链接到一些通用的
Atomic::cmpxchg
,然后您必须根据您的平台(这里是linux-amd 64)通过一些模板层跟踪到适当的实现。ovfsdjhp2#
实现起来相当简单,分为两个部分:一个JNI方法,它使指令作为字节码解释计算的一部分可用;一个内在函数,它使指令在JIT编译器生成本机代码时可用。
JNI方法
cpp将实现显示为JNI方法:
Atomic::cmpxchg分派到执行CAS的各种策略,您可以在OS+CPU specific file:
也有1字节和8字节CAS的实现,但唯一的区别分别是
cmpxchgb
和cmpxchgq
。JVM固有
正如你的问题的注解中所提到的,这个方法也被标记为
@HotspotIntrinsicCandidate
.(在最近的JVM中是@IntrinsicCandidate
)。JVM通过类和方法名来保存list of all intrinsic candidates。类文件解析器将方法与声明的内部函数相关联。从那里,JIT编译器可以检测到对具有内部函数的方法的调用,并将其替换为内联版本或仅针对该指令的汇编片段。