了解CAS

CAS, 全称是compare and swap的缩写,中文解释为比较并交换。这是并发算法时用到的一种技术。

CAS所操作的有三个值:内存位置的值(V)、期望的原值(A)和新值(B)。如果期望的原值和当前在cpu中的值一致,则将B作为新值放到内存中。否则,不做操作。CPU

CAS其实是CPU的指令,java是通过JNI来完成CPU指令的操作。

计算机上是如何保证数据的原子操作,以下从计算机的角度面简单描述三种锁:
1、处理器自动保证内存操作的原子性

2、使用总线锁保证原子性,如果多个处理器对共享变量进行读写,就会存在各自操作共享变量,导致结果与期望的不一致。

原因是有可能多个处理器同时从各自的缓存中读取变量i,分别进行加一操作,然后分别写入系统内存当中。

解决这个问题需要处理是在CPU1对共享变上量进行操作时阻塞其他CPU对共享变量的操作。所以从总线上加锁。

3.对处理器内部缓存加锁。

CAS带来的三个问题

1、ABA问题

如果一个共享变量的值从A变成B,再从B变成A.那个根据CAS的算法,没有变化。

在jdk1.5之后这个问题得到解决:

/**
* Atomically sets the value of both the reference and stamp
* to the given update values if the
* current reference is {@code ==} to the expected reference
* and the current stamp is equal to the expected stamp.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
* @param expectedStamp the expected value of the stamp
* @param newStamp the new value for the stamp
* @return true if successful
*/
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}

2.内存开销较大

3.只能保证一个变量的原子性

在jdk1.5后提供对对象原子性操作

public class AtomicReference<V> implements java.io.Serializable {
private static final long serialVersionUID = -1848883965231344442L;

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicReference.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}

private volatile V value;

posted @ 2018-07-14 18:45  沙师弟的流沙河  阅读(352)  评论(0编辑  收藏  举报