Atomic 与 CAS

Atomic 原子类:

  1. 介绍一下 Atomic 原子类


原子类的一个操作时候不可中断的。即使在多线程时,一个操作一旦开始,就不会被其他线程干扰。

  1. 讲讲 AtomicInteger 的使用


AtomicInteger常用方法

  1. public final int get();//获取当前值
  2. public final int getAndSet(int newValue);//获取当前值,并设置新的值
  3. public final int getAndIncrement();//获取当前值,并自增
  4. public final int getAndDecrement();//获取当前值,并自减
  5. public final int getAndAdd(int delta);//获取当前值,并加上预期的值
  6. boolean compareAndSet(int expect,int update);//如果当前值等于预期值,则以CAS的方式设置为新值
  7. public final void lazySet(int newValue);//最终设置为newValue值,使用lazySet设置之后可能导致其他线程在之后一段时间内读到旧值
  1. 能不能给我简单介绍一下 AtomicInteger 类的原理


AtomicInteger类主要利用CAS(Compare and swap)+volatile+native方法来保证操作原子性。其中CAS指拿预期的值和原本的一个值作比较,如果相同则更新成新的值。而volatile关键字保证该值的可见性,也就是说线程读取的都是内存的最新值。

CAS

  1. 原理


即Compare and swap,是一种有名的无锁算法,在不用锁的情况下实现多线程间的同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也称非阻塞同步。
CAS算法涉及到三个操作数:

  • 需要读写的内存值V
  • 进行比较的值A
  • 待写入的新值B
  1. CAS缺点

  1. ABA问题:一个变量V初次读取值为A,在赋值前检查到值仍然为A,这不代表这个值没有被修改过,因为在这段时间内它可能被修改为B,之后再修改回A,CAS操作因此就认为它没有被修改过。针对这种情况,Java 提供了 AtomicStampedReference 工具类,通过为引用建立类似版本号(stamp)的方式,来保证 CAS 的正确性。
  2. 循环时间开销