原子操作
一个事务包含多个操作,这些操作要么全 部执行,要么全都不执行。
CAS
CAS 操作包括三个运算符:内存地址 V,期望值 A 和新值 B
1)操作的时候如果地址上存放的值等于期望值A,则将地址上的值赋为新值B,并返回原值。
2)
如果地址上存放的值不等于期望值A,不做任何操作。
3)CAS 操作执行完成时,在业务上不一定完成了
,这时就要对CAS 操作进行反复重试,
直到成功为止。Java 中的Atomic系列的原子操作类的实现就是利用循环 CAS 来实现的。
4)ABA问题
如果一个值原来是 A,变成了B,又变成了 A,那么使用 CAS 检查时会发现它的值没有发生变化,但是实际上却发生了变化
解决思路就是使用版本号。在变量前面追加版本号,每次变量更新的时候把版本号加 1,那么 A→B→A 就会变成 1A→2B→3A。
5)问题
①自旋 CAS 如果长时间不成功,会给 CPU 带来非常大的执行开销
②对一个共享变量执行操作时,我们可以使用循环 CAS 的方式来保证原子操作,但是对多个共享变量操作时,CAS 就无法保证操作的原子性。
③多个共享变量操作如果要保证原子性,可以用锁或者把多个共享变量合并成一个共享变量来操作。比如两个共享变量 i=2,j=a,合并一下 ij=2a,然后用 CAS 来操作。
Atomic
Java 1.5 开始,JDK
提供了
AtomicReference
类来保证引用对象之间的原子性,就可以把
多个变量放在一个对象里来进行
CAS
操作
1)AtomicInteger
2)AtomicIntegerArray
3)更新引用类型
AtomicReference
AtomicStampedReference
AtomicMarkableReference
AtomicStampedReference
AtomicMarkableReference
4) 原子更新字段类
AtomicIntegerFieldUpdater
AtomicLongFieldUpdater
AtomicReferenceFieldUpdater
AtomicReferenceFieldUpdater
5) LongAdder
6) 其他