Cla*_*Bao 4 c++ java-native-interface openjdk jvm compare-and-swap
这是OpenJDK6的hotspot/src/share/vm/prims/unsafe.cpp代码片段(从第1082行开始):
// JSR166 ------------------------------------------------------------------
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);
if (UseCompressedOops) {
update_barrier_set_pre((narrowOop*)addr, e);
} else {
update_barrier_set_pre((oop*)addr, e);
}
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
jboolean success = (res == e);
if (success)
update_barrier_set((void*)addr, x);
return success;
UNSAFE_END
Run Code Online (Sandbox Code Playgroud)
还添加了关键方法oopDesc :: atomic_compare_exchange_oop.
inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
volatile HeapWord *dest,
oop compare_value) {
if (UseCompressedOops) {
// 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 {
return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);
}
}
Run Code Online (Sandbox Code Playgroud)
在JVM的上下文中,此代码的用途是什么?我没有C++经验.
Atomic :: cmpxchg和Atomic :: cmpxchg_ptr依赖于操作系统和CPU和32位/ 64位.所以JVM在这里被拆分了.
编辑
正如史蒂夫指出的那样,CAS有其作为ABA问题的弱点,因此这里需要内存屏障以确保CAS在多线程环境中仍然是正确的.此外,由于CAS需要三个参数,地址,旧值和新值,因此此过程需要现代CPU.
编辑
使用新的C++ 0x标准(现在还没有正式发布?),是否意味着JVM不需要被调整?至少,在源代码级别.二进制文件仍然可以拆分,但它将由C++编译器处理.
这是一个JNI包装的CAS API,与记忆障碍的IA64架构.
编辑:有关CAS的说明:
将dest与比较值进行比较,如果匹配则将交换值分配给dest.
这是一个原子操作,这意味着在操作执行时没有其他处理器可以改变dest的值.
这里列出了没有原子操作可能发生的典型问题,"ABA问题"
http://en.wikipedia.org/wiki/ABA_problem
你为什么要使用CAS功能?
简单示例是一个计数器,如果您有多个线程递增计数器,请考虑增量过程的作用:
int i;
read the value of i
add one to the current value
save the value back to i.
Run Code Online (Sandbox Code Playgroud)
当另一个处理器读取i的值并在此处理器完成之前保存i + 1时会发生什么?
你最终得到i + 1而不是i + 2.