AtomicInteger原子类使用 CAS 替代锁,实现基本类似,我们本文以 AtomicInteger 为例来研究其究竟是如何实现无锁同步的.
前言
一个可以自动更新的int值。 AtomicInteger用于原子递增计数器之类的应用程序,并且不能用作Integer的替代品。 但是,此类确实继承了Number,以允许处理基于数字的类的工具和实用程序进行统一访问。
继承关系

- 继承关系easy

- 由于继承了 Number,所以可以把 Number 代表的数值转换为基本数值类型

属性
- 设置为使用 Unsafe.compareAndSwapInt 进行更新



- valueOffset 在静态代码块中完成初始化:

AtomicInteger 的初衷就是在不使用锁的前提下,实现原子的读-改-写操作,这是通过 Unsafe 类提供的 CAS 操作实现的,CAS 操作有底层 CPU 直接支持。
构造方法
AtomicInteger 提供两个构造函数
- 用给定值初始化 AtomicInteger

- 无参构造,初始值为 0

注意,该类所有方法都被 final 修饰,子类无法重写!
API 源码
get - 获取当前值

set - 设为给定值

lazySet - 延迟设值
JDK 1.6 时引入. 大部分场景直接用 set 即可,但 set 内存屏障将禁止重排序,这会带来一定的性能消耗,因此非常关心性能,而lazySet不会立刻(但最终会)修改旧值,别的线程看到新值的时间会延迟一些

getAndSet - 设新值,返旧值
因为 value 是 volatile 变量,所以对 value 的 read/write 具备 happens-before 关系,所以一个很容易想到的实现为:
AtomicInteger counter = new AtomicInteger();
int oldV = counter.get();
counter.set(10);
但该实现是错的,因为 counter.get() 与 counter.set(10) 之间可能插入其他线程的 set,所以 oldV 不能保证是 set(10) 执行时的 value 值,当然通过锁将 get 与 set(10) 变成原子操作可以满足需求,但我们使用 AtomicInteger 就是为了避免使用锁,所以也不能这么做. 于是有了getAndSet:

基本的运算操作
自增
- 以原子方式将当前值增加一(i++)

- 以原子方式将当前值增加一(++i)

自减
- 以原子方式将当前值减一(i--)

- 以原子方式将当前值减一(--i)

都是基于 Unsafe.getAndAddInt 实现的,该方法实现 value 加操作,且返回旧值。
任意值的加减


CAS 操作
compareAndSet

- 检查某条件是否成立
- 根据条件成功、失败执行不同操作
在业务代码中,这种操作一般用锁实现,但 AtomicInteger 原生提供的 compareAndSet 无锁完美解决. 只有 value 的当前值等于 expect 时,才把 value 设置为 update,同时如果设置成功则返回 true,否则返回 false。 借助返回值可以检测方法的执行结果,因此可以在循环操作中不断执行 compareAndSet,直到成功,在线程池的源码中,很多方法都是这种套路。
weakCompareAndSet
- 弱化版compareAndSet,可能会虚假地失败,并且不提供排序保证,因此,很少是compareAndSet的适当替代方法,JDK8源码中未曾使用过它,因为二者在 Java 源码层次是一模一样的.

总结
AtomicIntger 的关键是 compareAndSet 方法,基于它可实现乐观的无锁算法.其妙用在 线程池中有着淋漓尽致地体现