Open monsterhxw opened 5 months ago
源码: https://github.com/openjdk/jdk8u/blob/master/jdk/src/share/classes/sun/misc/Unsafe.java#L885-L887
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
compareAndSwapInt
源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/prims/unsafe.cpp#L1213-L1218
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) UnsafeWrapper("Unsafe_CompareAndSwapInt"); 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
源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/atomic.cpp#L70-L75
unsigned Atomic::cmpxchg(unsigned int exchange_value, volatile unsigned int* dest, unsigned int compare_value) { assert(sizeof(unsigned int) == sizeof(jint), "more work to do"); return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); }
源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp#L93-L100
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory"); return exchange_value; }
movl 0xc(%rbx), %ebx ; 从 rbx 寄存器加上偏移量 0xc 的内存的值 (dest 的内存地址),存入 edx 寄存器 movl 0x8(%r11), %ecx ; 加载 exchange_value 内存值到 ecx 寄存器 movl 0xc(%r11), %eax ; 加载 compare_value 内存值到 eax 寄存器 lock cmpxchgl %ecx, (%ebx) ; lock 指令 (锁总线,确保原子),将脏缓存写回内存 ; cmpxchgl 指令,比较 eax 寄存器中的值和 ebx 所指向内存的位置存储的值是否相等 ; 相等,将 ecx 寄存器的值存入 ebx 寄存器所指向的内存位置 ; 不等,将 ebx 寄存器所指向内存位置中的值存到 eax 寄存器中,作为返回
源码比较直观
源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp#L216-L226
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { // alternative for InterlockedCompareExchange int mp = os::is_MP(); __asm { mov edx, dest mov ecx, exchange_value mov eax, compare_value LOCK_IF_MP(mp) cmpxchg dword ptr [edx], ecx } }
Marc's Blog | Java’s Atomic and volatile, under the hood on x86
Sholck's Blog | cmpxchg kernel-api学习
gorden5566's Blog | jdk 里的 CAS 操作实现
Java 的 CAS 调用的是 Unsafe 类的 native 方法
源码: https://github.com/openjdk/jdk8u/blob/master/jdk/src/share/classes/sun/misc/Unsafe.java#L885-L887
Unsafe 的
compareAndSwapInt
的 native 方法实现源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/prims/unsafe.cpp#L1213-L1218
Atomic::cmpxchg
方法的实现源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/share/vm/runtime/atomic.cpp#L70-L75
Atomic::cmpxchg
方法,对应的操作系统 (Linux) 和指令集 (x86) 的具体实现源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp#L93-L100
根据上面的代码得到对应的汇编代码
Atomic::cmpxchg
方法,Windows OS 和指令集 (x86) 的具体实现源码: https://github.com/openjdk/jdk8u/blob/master/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp#L216-L226
Refs
Marc's Blog | Java’s Atomic and volatile, under the hood on x86
Sholck's Blog | cmpxchg kernel-api学习
gorden5566's Blog | jdk 里的 CAS 操作实现