Unsafe库如何保障原子变量的线程安全?解析CAS底层实现
关于Unsafe库CAS方法保障线程安全的原理
问题描述
在查阅Compare and Swap(CAS)底层实现时发现,AtomicInteger、AtomicLong等原子变量均依赖JNI的Unsafe库的compareAndSet()方法,但只能看到如下native方法定义,无法了解其线程安全的实现逻辑:
@HotSpotIntrinsicCandidate public final native boolean compareAndSetLong(Object o, long offset, long expected, long x);
核心原理
Unsafe的CAS方法之所以能保障线程安全,本质是直接依托CPU硬件层面的原子指令,而非Java层面的逻辑控制,具体细节如下:
- CPU原子指令支撑:不同架构的CPU提供了专门的原子CAS指令,比如x86架构的
cmpxchg指令,ARM架构的cas或ldrex/strex指令。这些指令在执行时会锁定内存总线(或缓存行),确保"比较-交换"的整个操作是原子性的——执行过程中不会被其他线程中断,也不会出现中间状态。 - HotSpot内在优化:方法上的
@HotSpotIntrinsicCandidate注解表明,HotSpot虚拟机不会走常规的JNI调用流程,而是直接用手写的汇编或机器码实现这个方法,直接对接硬件原子指令,既保证了原子性,又避免了JNI调用的性能损耗。 - 内存可见性保障:CAS操作会附带内存屏障指令(比如x86的
lock前缀、ARM的dmb指令),强制刷新缓存,确保操作前后的内存读写对所有线程可见,避免了多线程环境下的缓存不一致问题。 - 无锁同步的核心逻辑:CAS是无锁同步的基础,它不需要依赖操作系统的线程互斥锁(比如mutex),而是通过自旋重试的方式处理竞争。当多个线程同时操作同一个变量时,只有一个线程能成功执行CAS,其他线程会重试直到成功或放弃,全程靠硬件原子性保证线程安全,避免了上下文切换的开销。
内容的提问来源于stack exchange,提问作者user2606235
相关产品推荐
相关产品推荐

