CAS(CompareAndSwap),顾名思义,CAS就是比较和交换。
简单来说CAS操作涉及三个值,分别是待修改的值E,要修改的新值V,以及待修改值所对应的内存位置的取值N。
(1)首先读取并记录待修改的值E
(2)然后计算新值V
(3)比较E和该内存位置的值,如果相等->(4);如果不相等->(5);
(4)更新为新值
(5)更新失败
CAS的应用
在java程序的多线程环境中,如果一个变量被多个线程访问,要保证线程安全,除了 volatile、锁、final、static这些手段外,可以借助java提供的 sun.misc.Unsafe类
这个类两个特点:
1.平台相关的(java语言平台无关),所有方法为native类型,c语言写的。提供了很多native类型方法
更详细点的源码可以看-->OpenJDK中的Unsafe
2.我们可以以不安全的方式使用这个类,在下面的代码中getUnsafe()给出了推荐的使用方式。使用这个类时也可以借鉴一些JDK中自带的类,比如并发包中的原子类、Random、LockSupport.park()、ConcurrentHashMap等。
CAS的ABA问题
如果待修改的值在CAS执行第二步的过程中被其他线程访问并修改,并且在第三步之前又修改为最初的值,例如先+1再-1。
此时虽然CAS执行成功,但是值已经不是最初的值了。
针对ABA问题的解决方案:
可以在对象中添加时间戳或者说版本号,AtomicStampedReference类提供了解决办法,在对象之中又添加了stamp时间戳属性避免其他线程修改了多次并变回修改前的value值,但对比stamp不同便可知道对象是被修改过的,只有提供属性值和stamp时间戳相等才能成功执行CAS修改操作,里面包裹了一个键值对对象AtomicStampedReference.Pair<V> pair类型,pair中值为属性值,value为stamp时间戳,在执行CAS操作时需要提供原值的value和时间戳都相等的情况才能成功执行CAS操作。