✨CAS全稱"Compare And Swap",也就是"比較并替換";它涉及三個操作數:記憶體值、預期值、新值。隻有當記憶體值和預期值一緻時,才能将記憶體值修改為新值。

📚CAS操作具有原子性,它的原子性由CPU硬體指令來保證;在Java的Unsafe.class定義了大量的原子操作。以CompareAndSwapInt()方法為例,分析彙編的實作。
找到HotSpot的Unsafe.cpp檔案,/src/share/vm/prims/Unsafe.cpp,最終會調用到下面這個方法
/**
* jobject obj : 共享變量所在的對象
* offset:偏移量,也就是對象的大小
* e :預期值
* x : 新值
*
*/
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;
最終會調用到src/os_cpu/atomic_linux_x86.inline.hpp(我以x86架構為例)
#define LOCK_IF_MP(mp)"cmp $0, " #mp"; je 1f; lock; 1: " //如果是多核CPU,會将lock傳回
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
int mp = os::is_MP(); //判斷是否是多核CPU
__asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" //%1:交換值 (exchange_value), %3:比較值(compare_value)
: "=a" (exchange_value)
: "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp)
: "cc", "memory");
return exchange_value; //傳回交換值
}
lock字首指令是核心,帶lock字首的指令在執行期間會鎖住整個總線,使得其他線程無法通過總線通路主記憶體;後續科學家們對其進行了優化,如果攜帶lock字首指令執行期間能夠命中緩存,且通路的記憶體值包含在一個緩存行(64位元組),則緩存行将被鎖定,其他線程就無法通路。
🔔(1) 鎖定緩存行(如果緩存命中,且記憶體值小于一個緩存行大小(64位元組)
🔔(2) 鎖定總線
❓ABA問題是什麼?
A線程在執行過程中,B線程快速的操作變量之後又将其值進行了還原。導緻這個過程對于B線程是不可見的。