JDK源码分析之CAS
2019-10-17 本文已影响0人
一岁一枯荣啊
一,什么是CAS?
(Conmpare And Swap)对比并替换。它将内存的内容与对比值进行校验,相同则替换,否则返回false.
两步操作,但是由于底层硬件的支持,两步操作能一步完成,避免独占锁资源浪费,保证了原子性
/Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/jre/lib/rt.jar!/java/util/concurrent/atomic
二、JAVA中CAS是怎么是实现的
JAVA中的CAS操作都是通过sun包下Unsafe类实现的,而Unsafe类中的方法都是native方法,由JVM本地实现
*/
public final void lazySet(int newValue) {
unsafe.putOrderedInt(this, valueOffset, newValue);
}
/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful. False return indicates that
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
* <p><a href="package-summary.html#weakCompareAndSet">May fail
* spuriously and does not provide ordering guarantees</a>, so is
* only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
* @return {@code true} if successful
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
/**
* Atomically decrements by one the current value.
*
* @return the previous value
*/
public final int getAndDecrement() {
return unsafe.getAndAddInt(this, valueOffset, -1);
}
/**
* Atomically adds the given value to the current value.
*
* @param delta the value to add
* @return the previous value
*/
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
/**
* Atomically decrements by one the current value.
*
* @return the updated value
*/
public final int decrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
}
三、ABA问题
比如内存中一数据 str="A";
第一步: 线程1取出str 的值"A",准备执行变更为"D",还未执行
第二步: 线程2取出str 的值"A" ,执行cas("A","B") ,把值变成了"B"
第三步: 线程3取出str 的值"B" ,执行cas("B","A") ,把值变成了"A"
第四步: 线程1继续执行cas("A","D")
这个过程就是有ABA问题存在的。因为在线程一执行的中间,数据已经被其他线程修改从而发生了变化,虽然恢复了原值,但是线程1没有感知到,以为没有发生过变化,这是不能被忽略的。
解决方式:JAV提供了时间戳的CAS。AtomicStampedReference
三、哪里用到了CAS
- AbstractQueuedSynchronizer
- ThreadPoolExecuter addWorker方法