Java并发的CAS原理与ABA问题的讲解
CAS原理
在计算机科学中,比较和交换(Compare And Swap)是用于实现多线程同步的原子指令。 它将内存位置的内容与给定值进行比较,只有在相同的情况下,将该内存位置的内容修改为新的给定值。 这是作为单个原子操作完成的。 原子性保证新值基于最新信息计算; 如果该值在同一时间被另一个线程更新,则写入将失败。 操作结果必须说明是否进行替换; 这可以通过一个简单的布尔响应(这个变体通常称为比较和设置),或通过返回从内存位置读取的值来完成(摘自维基本科)
CAS流程
以AtomicInteger.addAndGet()为例讲解CAS
javadoc
public final int addAndGet(int delta)
Atomically adds the given value to the current value, with memory effects as specified by VarHandle.getAndAdd(java.lang.Object…).
Parameters:
delta - the value to add
Returns:
the updated value
在Java的源码中
public final int addAndGet(int delta) { return U.getAndAddInt(this, VALUE, delta) + delta; }
这里的VALUE是在该类初始化的时候获取到的,理解一下就是这时候我们调用unsafe的objectFieldOffset
从Atomic类文件中获取value的偏移量,那么VALUE
其实就是记录value的偏移量的。
VALUE准确的是value这个字段相对与AtomicInteger这个对象内存起始地址的偏移量,由于这个方法的最底层是JNI调用native的方法,所以需要传入这个值。
private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");
继续往下执行:
/** * Atomically adds the given value to the current value of a field * or array element within the given object {@code o} * at the given {@code offset}. * @param o object/array to update the field/element in * @param offset field/element offset * @param delta the value to add * @return the previous value * @since 1.8 **/ @HotSpotIntrinsicCandidate public final int getAndAddInt(Object o, long offset, int delta) { int v; do { v = getIntVolatile(o, offset); } while (!weakCompareAndSetInt(o, offset, v, v + delta)); return v; }
@HotSpotIntrinsicCandidate public final boolean weakCompareAndSetInt(Object o, long offset, int expected, int x) { return compareAndSetInt(o, offset, expected, x); }
如果obj内的value和expect相等,就证明没有其他线程改变过这个变量,那么就更新它为update,如果这一步的CAS没有成功,那就采用自旋的方式继续进行CAS操作。从代码中看着也是两个步骤,但其实在JNI里是借助于一个CPU指令完成的,实际还是原子操作。
ABA问题
产生ABA问题的原因
CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。这就是CAS的ABA问题。
如何规避ABA问题
常用的办法是在更新数据的时候加入版本号,以版本号来控制更新。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接
您可能感兴趣的文章:
- 【Java并发编程】2、无锁编程:lock-free原理;CAS;ABA问题
- Java并发学习(十)-CAS中ABA问题解决方法
- 聊聊高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference源码来看如何解决CAS的ABA问题
- 谈论高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference看看如何解决源代码CAS的ABA问题
- Java并发编程笔记 Native方法,CAS操作与ABA问题
- Java并发之CAS与原子类实现原理讲解
- Java 并发与多线程规范(4) 自旋锁是可重入的吗?CAS与自旋锁的关系,CAS的ABA问题,以及乐观锁,悲观锁,互斥锁,读写锁的整理
- Java CAS 和ABA问题
- 【转】Java多线程编程(十)-并发编程原理(分布式环境中并发问题)
- java高并发:CAS无锁原理及广泛应用
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
- java并发:CAS算法和ABA问题
- Java CAS 和ABA问题
- java CAS 和ABA问题
- CAS操作实现并发的优势、以及实现一个无锁队列、怎样解决ABA 问题
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
- java并发前身CAS原理深度分析
- Java CAS 和ABA问题
- (java并发)CAS操作原理以及Atomic的原理