CAS(compare and swap)

CAS(compare and swap)

CPU并发原语。原语的执行是连续的,不允许中断,是线程安全的

比较当前工作内存的值与主内存的值是否一致,如果相同则执行规定操作,否则继续比较直到主内存和工作内存中的值一支为止。

AtomicInteger

1
2
3
4
5
AtomicInteger atomicInteger = new AtomicInteger(initialValue:5); 
// 先判断ecpected 与 初始值是否相同
// 相同 更新操作 返回true
// 不相同 更新失败,放弃操作,读取最新值,直到操作成功;
atomicInteger.compareAndSet(expect:5,update:2019);//

原理

1
2
3
public final boolean (int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
  • 自旋锁 do-while循环比较

  • unsafe类

    • JVM中 rt.jar-> sun.misc.Unsafe 需要通过本地(native)方法访问,像C指针直接操作内存

    • valueOffest 内存中偏移地址

缺点

  • 不加锁,并发性加强,可以保证一致性,但是循环比较时间长,如果匹配失败,会一直尝试,长时间不成功,给CPU带来了很大的开销。
  • 只能保证一个共享变量的操作。加锁可以保证多个变量的操作。
  • ABA问题。

ABA问题

复制和比较之间被其他线程修改,但是最终的值没有改变。 ABBBBA!

解决ABA问题
  • 原子引用 + 版本号

    • Class AtomicReference

      1
      2
      3
      4
      5
      AtomicReference<User> atomicReference = new AtomicReference();
      User user1 = new User("1");
      User user2 = new User("2");
      atomicReference.set(user1);
      atomicReference.compareAndSet(user1,user2);

原子引用更新

  • AtomicStampedReference

    stamp = atomicStampedReference.getStamp();