11、CAS原理與實現:
1、定義:
比較和交換(Conmpare And Swap,簡稱CAS)是用於實現多執行緒同步的原子指令。
JAVA中的CAS操作都是通過sun包下Unsafe類實現,而Unsafe類中的方法都是native方,
native方法的實現位於unsafe.cpp
原始碼流程如下:
java中方法(以AtomicInteger為例):
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
//物件o中offset偏移位置的值等於期望值(expected),
//就將該offset處的值更新為x,當更新成功時,返回true,
//native標記的方法在C++底層實現
public final native boolean compareAndSwapInt(Object o, long offset,
int expected, int x);
unsafe.cpp中C++方法(compareAndSwapInt實現):
//定義
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env,
jobject unsafe, jobject obj, jlong offset, jint e, jint x))
UnsafeWrapper("Unsafe_CompareAndSwapInt");
//判斷obj是否為空,返回obj指標的值
oop p = JNIHandles::resolve(obj);
//用p的地址加上offset得到具體記憶體地址
jint* addr = (jint *) index_oop_from_field_offset_long
(p, offset);
//通過Atomic::cmpxchg實現比較替換,其中引數x是即將更新的值,
引數e是原記憶體的值
return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END
//內聯彙編
inline jint Atomic::cmpxchg (jint exchange_value,
volatile jint* dest, jint compare_value) {
int mp = os::isMP(); //判斷是否是多處理器
//volatile表示禁止編譯器優化
__asm__ volatile (
//根據當前系統是否為多核處理器決定是否為cmpxchg指令
新增lock字首
LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"
: "=a" (exchange_value)
: "r" (exchange_value), "a" (compare_value), "r" (dest),
"r" (mp)
: "cc", "memory");
}
總結:
CAS操作實現:
用預期值A1和記憶體值A2做對比,如果A1等於A2,則記憶體值修改成B並返回true,
否則不操作並返回false。
缺點:
ABA問題:多執行緒時,其餘執行緒修改記憶體值之後又還原為初始值,
當前執行緒比較值時,值一樣則操作成功。
解決辦法:
java併發包中提供了一個帶有標記的原子引用類AtomicStampedReference,
通過控制變數值的版本來保證CAS的正確性。
AtomicStampedReference以一個int值作為版本號,
每次更改前先取到這個int值的版本號,
等到修改的時候,比較當前版本號與當前執行緒持有的版本號是否一致,
如果一致,則進行修改,並將版本號+1。
複製程式碼