CAS(Compare and Swap),本质是乐观锁的概念:有3个值,内存值V,预期值A,要修改的新值B,当且仅当内存值V与预期值A相等时,将内存值V的值修改为B
实际应用,浏览器上,多人打开同一篇文章进行编辑,存在问题:a打开编辑的时候,b也打开了,此时b先进行保存,a再保存,那a会把b编辑的内容覆盖掉。
CAS的做法如下:
步骤 | 数据库 | 页面a | 页面b |
1 | value=A | 页面刚打开的时候,将数据库的值带到页面,value=A | 页面刚打开的时候,将数据库的值带到页面,value=A |
2 | value=A | value=A | 先一步编辑并保存,value=A传到后台,跟数据库版本进行比较,两边都是A,能修改,将数据库的value改成B,value=B |
4 | value=B | 1、编辑并保存,value=A传到后台,跟数据库的值B进行比较,两者不相等,更新失败 2、刷新页面,重新从数据库拉值到页面,value=B,重复步骤1开始操作(自旋) | value=B |
会出现问题:
CAS会出现ABA问题,比如页面a在修改的时候,页面b进行了多次操作,先把值改成B,再把值改成A,这种情况页面a是无法感知的,java并发包引入AtomicStampedReference来解决该问题。
解决办法:多页面编辑的业务场景,通常引入版本号,如version=“2021-03-03 00:00:00"(也可以换成时间戳),每次更新的时候带上版本号。