什么是CAS
compare and swap
以CAS
的方式对属性private int value = 0;
进行递增操作
- 读取
value
的值 - 将其赋值给临时变量
a
,此时a = 0;
- 从
a
中获取值进行计算,将所得结果赋值给变量b
,此时a = 0; b =1;
- 重新读取
value
的值,与a
进行比较 - 如果两个值相等,则将
b
中的值写入到value
中 - 如果不相等,则从头开始读取
value
的,赋值给a
,计算,再进行读取比较,直到赋值成功为止!
源码
以AtomicInteger
为例,追溯其incrementAndGet
的逻辑
AtomicInteger counter = new AtomicInteger();
counter.incrementAndGet();
在incrementAndGet
方法中
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
incrementAndGet
方法先increment
然后 get
调用了sun.misc.Unsafe
类的 getAndAddInt
方法,而里面调用的是 getAndAddInt
,是先get
然后再add
,所以这里需要加1
getAndAddInt
中
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, v + delta));
return v;
}
调用 compareAndSwapInt
方法,而此方法是一个native
方法,因此我们需要从hotspot
源码src/share/vm/prims/unsafe.cpp
中的实现
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
方法,在src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp
中
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;
}
这里调用了汇编中的cmpxchgl
指令