注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html,而后自己结合hotspot源码看的
在sun.misc.Unsafe中CAS方法如下:
来看下openJDK8的hotspot中,unsafe是如何实现的,链接http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/prims/unsafe.cpp
图1
List-1
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h);//更新后的值
oop e = JNIHandles::resolve(e_h);//期望值
oop p = JNIHandles::resolve(obj);//更新的对象
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);//获取偏移地址,可以理解为获取要更新的属性的内存地址
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);//调用方法执行CAS操作
jboolean success = (res == e);//atomic_compare_exchange_oop的返回值是否等于期望值,如果等于,则success为true
if (success)
update_barrier_set((void*)addr, x);//更新memory barrier
return success;
UNSAFE_END
atomic_exchange_oop声明在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/oops/oop.hpp中,如下
List-2
static oop atomic_compare_exchange_oop(oop exchange_value,
volatile HeapWord *dest,
oop compare_value,
bool prebarrier = false);
实现在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/oops/oop.inline.hpp中,如下List-3所示:
List-3
inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
volatile HeapWord *dest,
oop compare_value,
bool prebarrier) {
if (UseCompressedOops) {
if (prebarrier) {
update_barrier_set_pre((narrowOop*)dest, exchange_value);
}
// encode exchange and compare value from oop to T
narrowOop val = encode_heap_oop(exchange_value);
narrowOop cmp = encode_heap_oop(compare_value);
narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp);//核心
// decode old from T to oop
return decode_heap_oop(old);
} else {
if (prebarrier) {
update_barrier_set_pre((oop*)dest, exchange_value);
}
return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);//核心
}
}
如上的List-3所示,核心的CAS调用Atomic::cmpxchg(val, (narrowOop*)dest, cmp)和Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value)。
cmpxchg的实现是在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/share/vm/runtime/atomic.cpp中,如下List-4所示
List-4
jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_value) {
assert(sizeof(jbyte) == 1, "assumption.");
uintptr_t dest_addr = (uintptr_t)dest;
uintptr_t offset = dest_addr % sizeof(jint);
volatile jint* dest_int = (volatile jint*)(dest_addr - offset);
jint cur = *dest_int;//对象当前值
jbyte* cur_as_bytes = (jbyte*)(&cur);
jint new_val = cur;
jbyte* new_val_as_bytes = (jbyte*)(&new_val);
new_val_as_bytes[offset] = exchange_value;
//这里有个for循环,资料上说“ 比较当前值与期望值,如果相同则更新,不同则直接返回”?
while (cur_as_bytes[offset] == compare_value) {
jint res = cmpxchg(new_val, dest_int, cur);
if (res == cur) break;
cur = res;
new_val = cur;
new_val_as_bytes[offset] = exchange_value;
}
return cur_as_bytes[offset];
}
cmpxchg_ptr的实现由不同的系统而实现不同,以64位linux为例,是在http://hg.openjdk.java.net/jdk8u/jdk8u60/hotspot/file/37240c1019fd/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp中
(adsbygoogle = window.adsbygoogle || []).push({});