原子操作
原子操作是指一个或者多个不可再分割的操作。这些操作的执行顺序不能被打乱,这些步骤也不可以被切割而只执行其中的一部分
java可以通过锁和循环CAS实现原子操作
一:使用循环CAS实现原子操作:利用CMPXCHG指令,自旋CAS就是循环到CAS操作成功为止
CAS是英文单词Compare and Swap的缩写,翻译过来就是比较并替换。
CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
从思想上来说,synchronized属于悲观锁,悲观的认为程序中的并发情况严重,所以严防死守,CAS属于乐观锁,乐观地认为程序中的并发情况不那么严重,所以让线程不断去重试更新。
在java中除了上面提到的Atomic系列类,以及Lock系列类夺得底层实现,甚至在JAVA1.6以上版本,synchronized转变为重量级锁之前,也会采用CAS机制
三大问题(应该只是解决思路,还没有实际应用去解决):
1)ABA问题:CAS需要操作值时需要检查值有没有发生变化,但是A->B->A,这样过程变了,但是结果没变,CAS就认为这没有发生变化(实际却是发生了变化的)
解决:变量前面加上版本号,每次更新就加一(就是多加了一个区分标志)
2)循环时间长开销大:如果自旋长时间不成功,会有很大的CPU开销
解决:JVM支持pause指令(1:延迟流水线执行指令 2:避免退出循环时因内存顺序冲突导致流水线被清空)
3)只能保证一个共享变量的原子操作:多个共享变量不能保证原子性
解决:可以用锁,或者把多个共享变量合并成一个来操作
二:用锁实现原子操作:锁保证只有获得锁的线程才能操作锁定的内存区域(强制排队) 轻,重量级锁都用循环CAS(获取,释放都是)