JoJo的个人博客

记录精彩的程序人生

目录
CAS自旋
/  

CAS自旋

概述

CAS的全称是Compare And Swap 即比较交换,是一种乐观锁机制

  • 执行函数:CAS(V,E,N) 其包含3个参数
    • V 表示要更新的变量
    • E 表示预期值
    • N 表示新值

如何要更新的变量等于预期值,就把新值赋值给变量,如何要更新的变量不等于预期值,就CAS再重新试一下,再试的时候,会重新读取要更新的变量作为预期值

比方说: 当前的这个线程想改这个值,我期望你是0,你就不能是1;如果是1,那就说明我这个值不对,然后想把你变成1。大概就是:原来这个值是变为3了,我这个线程想修改这个值的时候我一定期望你现在是3,是3我才改,如果在我修改的过程你变4了,说明就有另外一个线程修改过该值,那我cas就再重新试一下,再试的时候,我希望你的这个值是4,在修改的时候期望值是4,没有其它线程修改该值,那好我给你改成5,这样就是cas操作

cas 是 cpu 指令级别上的支持

当你判断的时候,发现是我的期望值,还没有进行新值设定的时候值又被别的线程改变了怎么办?答案是否定的,cascpu的原语支持,也就是说cascpu指令级别上的支持,中间不能被打断,不会造成所谓的数据不一致问题

ABA 问题

假设这样一种场景,当第一个线程执行CAS(V,E,U)操作,在获取到当前变量V,准备修改为新值U前,另外两个线程已连续修改了两次变量V的值,使得该值又恢复为旧值,这样的话,我们就无法正确判断这个变量是否已被修改过

Java中解决ABA问题,我们可以使用以下原子类:

  • AtomicStampedReference 类

AtomicStampedReference原子类是一个带有时间戳的对象引用,在每次修改后,AtomicStampedReference不仅会设置新值而且还会记录更改的时间。当AtomicStampedReference设置对象值时,对象值以及时间戳都必须满足期望值才能写入成功,这也就解决了反复读写时,无法预知值是否已被修改的窘境

  • 加版本,做任何一个值的修改,修改完加一,后面检查的时候连同版本号一起检查

参考文章

CAS(自旋)原理解析,及 ABA 问题

ConcurrentHashMap 的 CAS 操作


标题:CAS自旋
作者:SunnySky
地址:https://www.tianyang.pub/articles/2020/06/02/1591083118841.html

评论