CAS简介
CAS即Compare-and-Swap的缩写,即比较并交换,它是一种实现乐观锁的技术.在CAS中包含三个操作数:
V: 需要读写的内存位置,从java角度你可以把它当成一个变量
A: 预期值,也就是要进行比较的值
B: 拟写入的新值
当且仅当V的值等于A时,CAS才会通过原子方式用新值B来更新V的值,否则不会执行任何操作.无论位置V的值是否等于A,最终都会返回V原有的值.换句话说:"我认为V的值应该是A,如果是,那么就将V的值更新为B,否则不修改并告诉V的实际值是多少".
当多个线程使用CAS同时更新同一个变量时,只有其中一个线程能够成功更新变量的值,其他线程都将失败.和锁机制不同,失败的线程并不会被挂起,而是告知用户当前失败的情况,并由用户决定是否要再次尝试或者执行其他操作,其典型的流程如下:
image-20180910121551030
传统锁实现CAS语义
在明白CAS的语义后,我们用传统的锁机制来实现该语义.
public class SimpleCAS { private int value; public int getValue() { return value;
} // 比较并交换语义,最终都返回原有值
public synchronized int compareAndSwap(int exectedValue, int newValue) { int oldValue = value; if (oldValue == exectedValue) {
value = newValue;
} return value;
} // 比较并设置语义,返回成功与否
public synchronized boolean compareAndSet(int exectedValue, int newValue) { return exectedValue == compareAndSwap(exectedValue, newValue);
}
}在上述代码中,compareAndSwap()用于实现"比较并交换"的语义,在此之上我们还实现了"比较并设置"的语义.
使用场景
CAS典型使用模式是:首先从V中读取值A,并根据A计算出新值B,然后再通过CAS以原子方式将V中的值变成B(如果在此期间没有任何线程将V的值修改为其他值).我们借助刚才的SimpleCAS实现一个计数器,借此来说明其使用场景:
// 线程安全的计数器public class SafeCounter { private SimpleCAS cas; public SafeCounter() { this.cas = new SimpleCAS();
} public int getValue() { return cas.getValue();
} public int increment() { int value; int newValue; do { // 读取旧值A
value = cas.getValue(); // 根据A计算新值B
newValue = value + 1;
} while (!cas.compareAndSet(value, newValue));// 使用CAS来设置新值B
return newValue;
}
}SafeCounter不会阻塞,如果其他线程同时更新计数器,那么会执行多次重试操作直至成功.到现在有关CAS的语义和使用已经说完,下面我们要说的是CAS在JAVA中的应用以及JVM中如何实现CAS.
CAS实现
通过传统的锁实现的CAS语义并非JVM真正对CAS的实现,这点需要记住.JVM中能够实现CAS本质是现代CPU已经支持Compare-and-Swap指令.从Java 5.0开始,JVM中直接调用了相关指令.
JVM对CAS的支持
有关原子性变量的操作被统一定义在atomic.hpp,并以模板方法提供,其路径为:
/OpenJDK10/hotspot/src/share/vm/runtime/atomic.hpp
template<typename T, typename D, typename U>inline D Atomic::cmpxchg(T exchange_value,
D volatile* dest,
U compare_value,
cmpxchg_memory_order order) { return CmpxchgImpl<T, D, U>()(exchange_value, dest, compare_value, order);
}template<typename T>struct Atomic::CmpxchgImpl<
T, T, T, typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type>
VALUE_OBJ_CLASS_SPEC
{ T operator()(T exchange_value, T volatile* dest, T compare_value,
cmpxchg_memory_order order) const { // Forward to the platform handler for the size of T.
return PlatformCmpxchg<sizeof(T)>()(exchange_value,
dest,
compare_value,
order);
}
};不同的平台PlatformCmpxchg实现不同,比如在mac平台上,其实现在
/OpenJDK10/hotspot/src/os_cpu/bsd_x86/vm/atomic_bsd_x86.hpp
// 1字节长度template<typename T>inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order /* order */) const {
STATIC_ASSERT(1 == sizeof(T)); // 内嵌汇编代码,最终调用cmpxchgb指令实现"比较并交换"
__asm__ volatile ( "lock cmpxchgb %1,(%3)"
: "=a" (exchange_value)
: "q" (exchange_value), "a" (compare_value), "r" (dest)
: "cc", "memory"); return exchange_value;
}// 4字节长度template<typename T>inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order /* order */) const {
STATIC_ASSERT(4 == sizeof(T));
__asm__ volatile ( "lock cmpxchgl %1,(%3)"
: "=a" (exchange_value)
: "r" (exchange_value), "a" (compare_value), "r" (dest)
: "cc", "memory"); return exchange_value;
}// 8字节长度template<typename T>inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order /* order */) const {
STATIC_ASSERT(8 == sizeof(T));
__asm__ __volatile__ ( "lock cmpxchgq %1,(%3)"
: "=a" (exchange_value)
: "r" (exchange_value), "a" (compare_value), "r" (dest)
: "cc", "memory"); return exchange_value;
}在window_x86平台中,其实现在/OpenJDK10/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.hpp
template<>template<typename T>inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order order) const {
STATIC_ASSERT(1 == sizeof(T)); // alternative for InterlockedCompareExchange
// 内嵌汇编代码,最终调用cmpxchg指令实现"比较并交换"
__asm {
mov edx, dest
mov cl, exchange_value
mov al, compare_value
lock cmpxchg byte ptr [edx], cl
}
}template<>template<typename T>inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T)); // alternative for InterlockedCompareExchange
__asm {
mov edx, dest
mov ecx, exchange_value
mov eax, compare_value
lock cmpxchg dword ptr [edx], ecx
}
}template<>template<typename T>inline T Atomic::PlatformCmpxchg<8>::operator()(T exchange_value,
T volatile* dest,
T compare_value,
cmpxchg_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
jint ex_lo = (jint)exchange_value;
jint ex_hi = *( ((jint*)&exchange_value) + 1 );
jint cmp_lo = (jint)compare_value;
jint cmp_hi = *( ((jint*)&compare_value) + 1 ); // 内嵌汇编代码,最终调用cmpxchg8b指令实现"比较并交换"8字节
__asm {
push ebx
push edi
mov eax, cmp_lo
mov edx, cmp_hi
mov edi, dest
mov ebx, ex_lo
mov ecx, ex_hi
lock cmpxchg8b qword ptr [edi]
pop edi
pop ebx
}
}
作者:涅槃1992
链接:https://www.jianshu.com/p/f009da2e4110
共同学习,写下你的评论
评论加载中...
作者其他优质文章
