《Java并发编程的艺术》——CAS(Compare and Swap)

CAS(Compare and Swap):CAS操作使用一个期望值与当前值比较,如果比较后发现相等,则用一个新值替代当前值。现可用java.util.concurrent.atomic包下的原子类使用compareAndSet()方法显示调用,实际上该包下的所有原子类的方法,基本都是CAS操作

但是CAS操作伴随着三个问题:

  • ABA问题:依照上文所说,CAS操作实际上是在检查值有没有发生变化,如果没有则更新。此时假如有一个变量原来值是A,更改为B,又更改为A,则CAS操作会认为该变量的值没有发生过修改,但是实际上是发生过了,这就发生了逻辑混乱。在Java中可以用atomic包下的AtomicStampedReference类解决ABA问题,这个类在更新值时会在值前加入一个版本号,版本戳为int类型。针对上述问题若采用了AtomicStampedReference之后,就是1A -> 1B -> 2A,就可以完美解决问题。还有一个AtomicMarkableReference类与之类似,只不过版本戳是boolean类型。
  • 自旋(循环)时间可能过长:先看一下CAS的源码,以AtomicInteger.getAndIncrement()为例,可以看到,真正的CAS操作被套在一个do-while循环里,这就意味着如果线程长时间得不到资源,就会一直循环等待,这个过程持续在占用CPU资源。
funciton getAndIncrement(){
	return unsafe.getAndAddInt();
}

function getAndAddInt(){
	...
	do{
		v = getIntVolatile();
	}while(!compareAndSwapInt());
}
  • 只能保证一个变量的原子操作,当我们要实现对多个变量的原子操作时,就只能用比如synchronized或者ReentrantLock等的悲观锁了。

你可能感兴趣的:(《Java并发编程的艺术》——CAS(Compare and Swap))