CAS

CAS: Compare and swap 比较和交换
在指令的级别,保证该操作的原子性。

原理

如果这个内存地址的值是我所期望的值,那么就把它设成新值。
比如,如果内存地址为100的位置的值是1,我想把值改为2,那么CAS赋值操作就是这样的:如果内存地址为100的位置值是1,那么就把值设为2.所以如果其他线程在此之前把值改为了3,则这个CAS赋值失败。因此就出现了自旋(死循环)CAS赋值操作(每次CAS期望的值都从内存中现取一份)。

基于这样的特性,CAS又可用于乐观锁。
悲观锁是每次执行代码都是先加锁再执行,所以叫悲观(认为竞争太激烈,直接加锁吧);
乐观锁是每次执行代码先尝试,不行的话再继续尝试,所以叫乐观(认为竞争不激烈,可以尝试)。

CAS存在的问题

  1. CAS长期不成功,则一直死循环。
  2. 版本问题(ABA问题)。比如CAS期望的值是A,其他线程把A改成B又改成A,CAS操作也会成功,但是并不意味着值没有发生过改变。解决方法就是加一个版本戳:A1->B2->C3,让CAS期望A1就好了。

jdk中的原子操作类 Atomic

解决版本问题有两个Atomic:

  1. AtomicMarkableReference,isMarked():boolean ,只关心有没有动过
  2. AtomicStampedReference ,getStamp():int,可以获取版本戳,关心动过几次
posted @ 2020-09-30 12:39  qianbuhan  阅读(195)  评论(0)    收藏  举报