我的博客java篇-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 指令级别上的支持
当你判断的时候,发现是我的期望值,还没有进行新值设定的时候值又被别的线程改变了怎么办?答案是否定的,cas是cpu的原语支持,也就是说cas是cpu指令级别上的支持,中间不能被打断,不会造成所谓的数据不一致问题
ABA 问题
假设这样一种场景,当第一个线程执行CAS(V,E,U)操作,在获取到当前变量V,准备修改为新值U前,另外两个线程已连续修改了两次变量V的值,使得该值又恢复为旧值,这样的话,我们就无法正确判断这个变量是否已被修改过
Java中解决ABA问题,我们可以使用以下原子类:
- AtomicStampedReference 类
 
AtomicStampedReference原子类是一个带有时间戳的对象引用,在每次修改后,AtomicStampedReference不仅会设置新值而且还会记录更改的时间。当AtomicStampedReference设置对象值时,对象值以及时间戳都必须满足期望值才能写入成功,这也就解决了反复读写时,无法预知值是否已被修改的窘境
- 加版本,做任何一个值的修改,修改完加一,后面检查的时候连同版本号一起检查