为什么要使用CAS?
CAS是compare and swap的缩写,即我们所说的比较交换,是一种乐观锁,java的锁分为悲观锁和乐观锁,悲观锁是将资源锁住,等一个之前获得锁的线程释放锁之后,下一个线程才可以访问。而乐观锁采取了一种宽泛的态度,通过某种方式不加锁来处理资源,比如通过给记录加version来获取数据,性能较悲观锁有很大的提高,在没有锁的状态下,CAS可以保证多个线程对一个值的更新。
CAS原理?
1、读取当前值,存到E里面
2、结果++
3、写1的时候,比较看原始值是不是还是0,如果没有人动过还是0就直接更新成1
4、如果有线程动过值,重新读取新值++,看还是不是原值,如果是就写入新值,如果不是就在重读读取新值++
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存地址里面的值和A的值是一样的,那么就将内存里面的值更新成B。CAS是通过无限循环来获取数据的,若果在第一轮循环中,a线程获取地址里面的值被b线程修改了,那么a线程需要自旋,到下次循环才有可能机会执行
CAS的问题
1.ABA问题?
就是女朋友跟你分手之后又经历了别的男人,之后又跟你复合了,中间的过程你不知道。中间已经把值改了,之后又改回来了,无感知,即ABA问题,
一般可以怎么解决?
1.加版本号,改动的时候加版本号,比较的时候不仅比较值,还比较版本号,
2.加布尔类型,改没改过用布尔类型标记一下。
2.CUP资源占用
因为CAS是循环判断的过程,所以如果没有获取到状态,CPU会一直被占用
CAS底层上是怎么实现的?
native方法,汇编机器语言实现
cmpxchg实现,是非原子性的,所以前面加了lock。