非阻塞算法:如果在某种算法中,一个线程的失败或挂起不会导致其他线程也失败或挂起,那么这种算法就被称为非阻塞算法。如果在算法的每个步骤中都存在某个线程执行下去,那么这种算法也被称为无锁(Lock_Free)算法。
原子变量类是Java为支持非阻塞算法而提供的对象。原子变量比锁的粒度更细,并发性能更好,通常在并发场景下进行变量的复合操作时使用,如:i++、if..get等
基本数据类:AtomicBoolean、AtomicInteger、AtomicLong
引用对象类:AtomicReference
数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
属性更新类:AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater
解决ABA问题的类:AtomicStampedReference、AtomicMarkableReference
说明:CAS包含了3个操作数:需要读写的内存位置V,进行比较的值A、待更新的值B,当且仅当V的值等于A时,通过原子方式更新V的值为B;当多个线程使用CAS同时更新同一个变量时,只有其中的一个线程能更新成功,其他线程都将失败,失败的线程不会阻塞。
应用场景:Java提供的原子变量类中的复合操作底层均通过CAS技术实现原子操作。
源码分析(以AtomicInteger#getAndIncrement()为例)
//i++的原子操作
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
//获取内存中共享变量var1的值
var5 = this.getIntVolatile(var1, var2);
//执行底层CAS操作:var1内存位置,var2本地缓存的值,var5共享内存中的值,当且仅当var2=var5时,var1的值更新为var5+var4
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
问题描述:ABA问题是一种异常现象——如果在算法中的节点可以被循环使用,那么在使用CAS时就可能出现这个问题。如线程1和2同时将变量X的值由A更新为B,线程1先将变量X的值由A改为C再改为A,此时线程2执行CAS更新变量X的值,发现变量X的值是没有变化的,但实际变量X的值已经发生过变化。
解决方案:引入一个变量——版本号,更新时需更新变量的值和版本号。如原子变量类AtomicStampedReference、AtomicMarkableReference。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章