原子类使用 CAS 替代锁,实现基本类似,我们本文以 AtomicInteger 为例来研究其究竟是如何实现无锁同步的.
前言
一个可以自动更新的int值。 AtomicInteger用于原子递增计数器之类的应用程序,并且不能用作Integer的替代品。 但是,此类确实继承了Number,以允许处理基于数字的类的工具和实用程序进行统一访问。
继承关系
继承关系easy
由于继承了 Number,所以可以把 Number 代表的数值转换为基本数值类型
属性
- 设置为使用 Unsafe.compareAndSwapInt 进行更新
- 注意到 unsafe 和 valueOffset 都是 static final 字段,而 value 有 volatile 修饰.
- valueOffset 在静态代码块中完成初始化:
- AtomicInteger 的初衷就是在不使用锁的前提下,实现原子的读-改-写操作,这是通过 Unsafe 类提供的 CAS 操作实现的,CAS 操作有底层 CPU 直接支持。
构造方法
AtomicInteger 提供两个构造函数
- 用给定值初始化 AtomicInteger
- 无参构造,初始值为 0
- 注意,该类所有方法都被 final 修饰,子类无法重写!
API 源码
get - 获取当前值
set - 设为给定值
由于 value 是 volatile 变量,通过内存屏障,set 对 value 的修改对其他线程是立即可见 的,无需添加 synchronized.
lazySet - 延迟设值
JDK 1.6 时引入.
大部分场景直接用 set 即可,但 set 内存屏障将禁止重排序,这会带来一定的性能消耗,因此非常关心性能,而lazySet不会立刻(但最终会)修改旧值,别的线程看到新值的时间会延迟一些
lazySet 具有 write(assign)volatile 变量的内存效果,除了它允许对后续(但不是先前)的内存操作进行重排序,而这些内存操作本身不会对普通的非 volatile 写入施加强加约束。 在其他使用上下文中,为了进行垃圾回收,lazySet 可能在清空时适用,以后再也不会访问该引用。