Java 原子类的实现
前言
juc.atomic 包下面的原子变量使用了乐观锁的一种 CAS 实现方式,了解其原理后,便可以模拟出Java原子类的实现
一、乐观锁与CAS
乐观锁
- 乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测
如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做
乐观锁适用于读操作多的场景,这样可以提高程序的吞吐量 - 应用:
juc.atomic 包下面的原子变量使用了乐观锁的一种 CAS 实现方式
版本号控制:一般是在数据表中加上一个数据版本号 version 字段,表示数据被修改的次数。当数据被修改时,version 值会+1。当线程A要更新数据值时,在读取数据的同时也会读取 version 值,在提交更新时,若刚才读取到的 version 值与当前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新成功
CAS
- 即CompareAndSwap,比较并交换
- CAS底层是lock cmpxchg 指令(X86架构),在单核CPU和多核CPU下都能够保证【比较-交换】的原子性
- CAS必须借助volatile才能读取到共享变量的最新值来实现【比较并交换】的效果
- 适用于线程数少、多核CPU的场景下
二、实现原子类
1.分析源码
通过查看AtomicInteger类的源码,可以发现,其中的绝大部分方法,都是通过直接调用Unsafe类的一个实例实现的,那么如果我们能使用Unsafe类,自己实现一个原子类,也就不是难事了。
AtomicInteger类部分源码:
public class AtomicInteger extends Number implements Serializable {
private static final Unsafe U = Unsafe.getUnsafe();
public final int getAndIncrement() {
return U.getAndAddInt(this, VALUE, 1);
}
public final int getAndDecrement() {
return U.getAndAddInt(this, VALUE, -1);
}