AtomicLong源码解析
AtomicLong是在JDK的java.util.concurrent.atomic包中提供的,线程安全的Long操作类。之所以说它是线程安全的,是相对于long类型的数据来说的。
比如下面这个例子:
1 | public class UseLongUnsafe implements Runnable { |
上述代码做的事情:
- 声明一个静态的long值value
- 实现Runnable接口,并实现其run方法
- 在run方法中对value自增1000次
- 开启10个线程,每个线程对value自增1000次
- 观察结果。
运行上述代码,可以发现每次跑完的结果都不一样:
这是因为int类型在自增的时候(i++或者++i),不是一个原子操作完成的。它大略可以分为三步
- 从原来的地址中取出值
- 对值加1
- 放回原来的地址
这三步中,任何一步在执行的时候,线程被切换走,都会导致最后结果的不一致。
因此,JDK就提供了一个采用CAS思想实现的原子类AtomicLong。
AtomicLong类介绍
类图
AtomicLong继承了抽象类Number,并实现了其longValue,doubleValue等方法。
主要属性
1 | // setup to use Unsafe.compareAndSwapLong for updates |
unsafe:sun提供的实现CAS的主要工具类
valueOffset:当前值value在整个AtomicLong对象中的内存偏移量。这个值在下面的代码块中完成初始化
1 | static { |
VM_SUPPORTS_LONG_CAS:记录底层JVM是否支持longs的无锁compareAndSwap。
虽然Unsafe.compareAndSwapLong方法在任何一种情况下都可以工作,
但是应该在Java级别处理一些构造以避免锁定用户可见的锁。
value:保存long的值
**VMSupportsCS8()**:返回底层JVM是否支持longs的无锁CompareAndSet。 仅调用一次并缓存在VM_SUPPORTS_LONG_CAS中。
主要方法
AtomicLong(long)
1 | /** |
指定初始值生成一个AtomicLong对象
AtomicLong()
1 | /** |
生成一个默认的AtomicLong对象。值默认为0
get()
1 | /** |
获取当前值
set(long)
1 | /** |
将value值设置为当前值newValue
lazySet(long)
1 | /** |
“慢慢”地将value的值设置为newValue。是一个最终一致性的方法。意味着,在极短的一段时间内,其他线程还是可能读取到value而不是newValue。
getAndSet(long)
1 | /** |
获取当前value的值,并将value的值设置为newValue
public final boolean compareAndSet(long, long)
1 | /** |
如果当前value的值为expect,那么将当前值设置为update。否则返回false。如果设置成功返回true,否则返回false。
public final boolean weakCompareAndSet(long, long)
1 | /** |
这个方法的本意是,调用weakCompareAndSet方法时不能保证指令重排的发生,因此,这个方法有时候会毫无理由地失败。
但是从实现上来看,该方法是和compareAndSet的实现是一致的。
getAndIncrement()
1 | /** |
获取当前的值并对当前的值加1
getAndDecrement()
1 | /** |
获取当前的值并对当前的值减1
getAndAdd(long)
1 | /** |
获取当前value的值并对该值加上delta。
incrementAndGet()
1 | /** |
对当前值加1,并返回更新后的值
decrementAndGet()
1 | /** |
对当前值减1,并返回更新后的值
addAndGet(long)
1 | /** |
对当前值加上delta,并返回更新后的值
getAndUpdate(LongUnaryOperator)
1 | /** |
获取当前值,并对当前值应用Long型单元函数,并将获得的结果设置为最新的value值。
updateAndGet(LongUnaryOperator)
1 | /** |
对当前值应用Long型单元函数,并将获得的结果设置为最新的value值,返回最新的value值。
getAndAccumulate(long,LongBinaryOperator)
1 | /** |
获取当前值,并对x和当前值value应用二元函数,并将得到的结果设置为最新的value值。
accumulateAndGet(long,LongBinaryOperator)
1 | /** |
对value和x应用二元函数,并将得到的结果设置为最新的value,并返回
toString()
1 | /** |
返回long型value的字符串类型
intValue()
1 | /** |
将当前的value转为int返回。需要注意类型变窄
longValue()
1 | /** |
返回当前值
floatValue()
1 | /** |
将当前值转为float返回
doubleValue()
1 | /** |
将当前值转为double返回
应用
下面将使用AtomicLong类改写上面多线程环境下不安全的代码。
1 | public class UseAtomicLong implements Runnable { |
改写之后,无论再怎么运行,都不会出现值不是10000的情况了。