CAS原理分析,解决银行转账ABA难题( 二 )


解决方法:在变量前面加上版本号,每次变量更新的时候变量的版本号都+1,即A->B->A就变成了1A->2B->3A 。
循环时间长开销大如果CAS操作失败,就需要循环进行CAS操作(循环同时将期望值更新为最新的),如果长时间都不成功的话,那么会造成CPU极大的开销 。

这种循环也称为自旋
解决方法:限制自旋次数,防止进入死循环 。
只能保证一个共享变量的原子操作CAS的原子操作只能针对一个共享变量 。
解决方法:如果需要对多个共享变量进行操作,可以使用加锁方式(悲观锁)保证原子性,或者可以把多个共享变量合并成一个共享变量进行CAS操作 。
CAS的应用我们知道CAS操作是一种无锁操作,并不会锁住共享变量,也就是一种非阻塞的同步机制,CAS就是乐观锁的实现 。
  1. 乐观锁总是假设最好的情况,每次去操作数据都认为不会被别的线程修改数据,所以在每次操作数据的时候都不会给数据加锁,即在线程对数据进行操作的时候,别的线程不会阻塞仍然可以对数据进行操作,只有在需要更新数据的时候才会去判断数据是否被别的线程修改过,如果数据被修改过则会拒绝操作并且返回错误信息给用户 。
  2. 悲观锁总是假设最坏的情况,每次去操作数据时候都认为会被的线程修改数据,所以在每次操作数据的时候都会给数据加锁,让别的线程无法操作这个数据,别的线程会一直阻塞直到获取到这个数据的锁 。这样的话就会影响效率,比如当有个线程发生一个很耗时的操作的时候,别的线程只是想获取这个数据的值而已都要等待很久 。
Java利用CAS的乐观锁、原子性的特性高效解决了多线程的安全性问题,例如JDK1.8中的集合类ConcurrentHashMap、关键字volatile、ReentrantLock等 。

【CAS原理分析,解决银行转账ABA难题】


推荐阅读