侧边栏壁纸
博主头像
月伴飞鱼 博主等级

行动起来,活在当下

  • 累计撰写 126 篇文章
  • 累计创建 31 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录
JVM

CAS使用了Volatile保证可见性的吗?

月伴飞鱼
2025-04-02 / 0 评论 / 1 点赞 / 11 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

一、问题澄清

CAS本身(如Unsafe.compareAndSwapInt)底层实现是否自带volatile语义?

答案是:

  • CAS底层通过JVM和CPU指令提供的原子操作实现。

  • CAS本身并不是通过Java的关键字volatile实现的,而是通过硬件的特殊指令(如cmpxchg)和JVM的底层实现方式,保证了volatile语义(可见性、禁止重排序)

也就是说:
CAS方法本身在Java层并不会显示地对变量加volatile关键字,但底层原理确保了CAS操作自带volatile语义。

二、从Java源码层面查看(Unsafe)

以常用的Unsafe类为例,源码位置:

JDK8: sun.misc.Unsafe(JDK11+ 为jdk.internal.misc.Unsafe

public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
  • 这个方法是native的,表示由JVM本地方法实现,Java层不直接控制volatile语义。

三、从OpenJDK源码(HotSpot)进一步跟踪:

以OpenJDK HotSpot源码为例:

  • Java的Unsafe.compareAndSwapInt底层对应的实现是HotSpot中对应的Unsafe_CompareAndSwapInt方法:

// hotspot/src/share/vm/prims/unsafe.cpp
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

此处调用Atomic::cmpxchg方法,这是原子操作的底层实现。

HotSpot原子操作定义:

  • HotSpot VM 对原子操作提供了统一封装,位于atomic.hpp中:

// hotspot/src/share/vm/runtime/atomic.hpp
template<typename T>
inline static T cmpxchg(T exchange_value, volatile T* dest, T compare_value);

注意:

  • 参数定义中明确使用了volatile T* dest,表示传入的变量指针具有volatile语义。

  • 这正是体现了CAS操作天然自带volatile语义的根源。

四、从汇编指令角度分析(x86为例):

  • CAS指令对应于x86 CPU指令lock cmpxchg

  • 使用lock前缀的指令可以实现两点:

    1. 原子性:总线加锁(或缓存一致性协议)。

    2. 内存屏障:隐含内存屏障指令效果(mfence),使得其他CPU核心可见变量的最新值(即volatile语义)。

因此,从CPU硬件指令层面,CAS指令(如lock cmpxchg)天然具备volatile语义:

  • 保证多线程下的可见性

  • 禁止指令重排

  • 保证数据的原子性更新

五、总结核心点:

综上所述:

层面

具体说明

volatile语义

Java层

Unsafe.compareAndSwapInt()为native方法,无volatile关键字

无显式

JVM层

HotSpot VM的实现中cmpxchg方法的入参为volatile

隐式volatile语义

硬件层

使用lock cmpxchg指令,天然自带内存屏障,保证可见性

隐式volatile语义

结论

  • CAS(Unsafe类的compareAndSwapXxx方法)并非通过Java代码中的volatile关键字实现volatile语义,而是通过底层JVM和CPU的实现,隐含地拥有了volatile所具备的内存屏障和可见性效果。

  • 因此,CAS本身确实是天然自带volatile语义,从而保证多线程下的可见性和顺序性。

公众号.png

1
JVM
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
    1. 支付宝打赏

      qrcode alipay
    2. 微信打赏

      qrcode weixin
博主关闭了所有页面的评论