cas是compare and swap的简写,也就是比较并交换。
他的内部实现是基于cpu指令完成的,所以他在java中是一个native方法。
那么他的作用是什么?是保证操作的原子性。
举个例子,我要让a这个值+1,那么此时a的值是0,我先拿到0这个值,然后我计算+1后得到的值是1,我在写回去的之前,我判断,当前这个值,还是不是0,如果是0则认为,我操作的这个过程中,没有其他人动过,那么我本次的改动就是允许的。
那么你可能会问,如果我在写回去的过程中,值被改了怎么办?不用担心,判断和写回去的这个操作是不会被打断的,这个涉及到cpu指令(底层会自己加锁来保证,颗粒度非常小)
如果我判断值被修改了怎么办?没关系,我重新获取这个值,然后继续+1,然后再次比较,直到成功。
当然,这个必然会出现非常多的失败的情况,比如10个线程同时操作,那么那一刻只有1个线程是成功的,另外9个是失败的,但是也比上锁时的线程切换消耗的性能要低。
所以他的优点就是性能好,特定情况下的性能好,在线程争抢不严重的情况,如果你说现在有160个线程,只有1个成功,那性能也好不了。这个时候建议使用LongAdder,他底层用了分段计算来减少这个失败的概率。
缺点就是会有ABA问题,也就是我在执行的过程中,别人先把a改成了8,然后又改回了0,此时我的判断依旧是成功的,但实际上此0非彼0,这个问题的解决方法我载额外增加一个版本号,我根据这个版本号来判断,我不管目标值是多少,我只要操作这个值,就让版本号+1,最后比较这个版本号就可以了,你改了8又改回0,那么版本号就会+2,那么就和我手上的版本号不一致了。