# 五、CAS

# 1. CAS

Compare and swap,是乐观锁的一种实现。

我认为V的值应该是A ,如果是的话那我就把它改成B ,如果不是A (说明被别人修改过了) , 那我就不修改了, 避免多人同时修改导致出错

CAS 有三个操作数:内存值V、预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才将内存值修改为 B,否则什么都不做。最后返回现在的V值。

image-20210321112615614

CAS 需要利用 CPU 的特殊指令 cmpxchg。

jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte*dest, jbyte compare_value) {
         assert (sizeof(jbyte) == 1,"assumption.");
         uintptr_t dest_addr = (uintptr_t) dest;
         uintptr_t offset = dest_addr % sizeof(jint);
         volatile jint*dest_int = ( volatile jint*)(dest_addr - offset);
         // 对象当前值
         jint cur = *dest_int;
         // 当前值cur的地址
         jbyte * cur_as_bytes = (jbyte *) ( & cur);
         // new_val地址
         jint new_val = cur;
         jbyte * new_val_as_bytes = (jbyte *) ( & new_val);
          // new_val存exchange_value,后面修改则直接从new_val中取值
         new_val_as_bytes[offset] = exchange_value;
         // 比较当前值与期望值,如果相同则更新,不同则直接返回
         while (cur_as_bytes[offset] == compare_value) {
          // 调用汇编指令cmpxchg执行CAS操作,期望值为cur,更新值为new_val
             jint res = cmpxchg(new_val, dest_int, cur);
             if (res == cur) break;
             cur = res;
             new_val = cur;
             new_val_as_bytes[offset] = exchange_value;
         }
         // 返回当前值
         return cur_as_bytes[offset];

# 2. 等价过程

private volatile int value;
public synchronized int compareAndSwap(int expectedValue, int newValue){
  	int oldValue = value;
    if(oldValue == expectedValue){
      value = new Value;
    }
    return 	oldValue;
}

# 3. 优缺点

# 3.1 优点

  • 在竞争不是很激烈的情况下性能比较高。

# 3.2 缺点

  • CPU 开销大,在高并发下,许多线程,更新一变量,多次更新不成功,循环反复,给 CPU 带来大量压力。

  • 只是一个变量的原子性操作,不能保证代码块的原子性。

  • ABA 问题:

    threadA 将100,改为50; threadB 将100,改为50; threadC 将50,改为100;

    这个时候并不会察觉到线程是否被修改过。

    # 如果解决?
    可以引入版本号这个字段,利用版本号来确定是否被修改过,而不是比较值本身。
    
上次更新: 9/17/2021, 12:28:06 PM