CAS中,如何避免比较和修改之间插入线程?
这说的并不是ABA问题,ABA问题是比较之前某个值被改变成另一个相同的值的问题
先来回顾原语:原子性的语句,就是一堆机器指令,CPU要么全部执行,要么全部不执行
JAVA中的CAS:
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5)
查看其native源码:
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);// 调用了另一个方法
jboolean success = (res == e); // 如果返回的res等于e,则判定满足compare条件(说明res应该为内存中的当前值),但实际上会有ABA的问题
if (success) // success为true时,说明此时已经交换成功(调用的是最底层的cmpxchg指令)
update_barrier_set((void*)addr, x); // 每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作,配合垃圾收集器
return success;
UNSAFE_END
可以看到源码中又调用了另一个原子性的方法:oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
保证其原子性,避免被其它线程插入;到最后会转换成完成CAS功能的原语
参考: