JUC 包中的原子类是哪4类?
基本类型
- AtomicInteger:整形原子类
- AtomicLong:长整型原子类
- AtomicBoolean:布尔型原子类
数组类型
- AtomicIntegerArray:整形数组原子类
- AtomicLongArray:长整形数组原子类
- AtomicReferenceArray:引用类型数组原子类
引用类型
- AtomicReference:引用类型原子类
- AtomicStampedReference:原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以
解决使用 CAS 进行原子更新时可能出现的 ABA 问题
- AtomicMarkableReference :原子更新带有标记位的引用类型
对象的属性修改类型
- AtomicIntegerFieldUpdater:原子更新整形字段的更新器
- AtomicLongFieldUpdater:原子更新长整形字段的更新器
CAS
原理
-
CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B
-
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B
-
CAS的自旋
1.获取当前值(用
volatile
保证获取的是最新的值)
2.当前值+1,计算出目标值
3.进行CAS操作,如果成功则跳出循环,如果失败则重复上述步骤 -
在JVM中的CAS操作就是基于处理器的
CMPXCHG
汇编指令实现的,因此,JVM中的CAS的原子性是处理器保障的
缺点
-
CPU开销较大: 在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力
-
不能保证代码块的原子性: CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用Synchronized了
-
ABA问题:
小明有余额100块,去汇款50块,由于系统故障,汇款请求发了2次
第一次汇款请求 CAS 期望100 更新50 – 余额为50块
小明老妈汇来了50块 – 余额为100块
第二次汇款请求 CAS 期望100 更新50 – 余额为50块
最终结果,2次汇款请求均成功处理,小明被多扣50块