你能聊聊CAS一般怎么用以及CAS工作原理是啥?

1、面试题

java里玩儿悲观锁和乐观锁一般怎么玩儿?synchronized相当于是悲观锁,CAS相当于是乐观锁。知道CAS是什么吗?CAS是如何实现的?

2、面试官心里分析

这个高级点的面试,肯定会问CAS,还是比较重要的

3、面试题剖析

悲观锁:我现在要操作一个共享数据,我很悲观,我认为我操作的过程中,一定会被人给修改,会导致数据错误;我在操作这个数据之前,先给这个数据加了一把锁,synchronized,在我操作这个数据的期间,就只能是我来操作,其他任何人都操作不了

乐观锁:我感觉在我操作这个数据的过程中,应该不会被人给修改。我先修改吗,然后修改完之后要设置这个变量的最新的值,此时我会对比一下,当前的这个值,是不是跟我在操作前看到的这个值是一样的,如果是一样的,那么说明可能就没有被人给修改过,如果没有被人修改过,那么我就可以来设置最新的值。

CAS,Compare and Swap,就是比较和交换。java并发包借助CAS实现了乐观锁的思想,synchronized是悲观锁思想。

CAS会操作3个数字,当前内存中的值,旧的预期值,新的修改值,只有当旧的预期值跟内存中的值一样的时候,才会将内存中的值修改为新的修改值。举个例子吧,比如int a = 3,这是内存中的当前值,然后你CAS(3, 5),第一个是旧的预期值,如果3和a是一样的,那么就将a修改为5。

 

其实吧,这里比较关键的一点就是cpu的compareAndSwap操作的原理是啥,以CPU(Intel X86)来举个例子。这块底层指令,会根据当前处理器类型,来决定要不要对一个cmpxchg指令加lock前缀,如果是单处理器,就不要加,因为自动保证顺序;但是如果是多处理器,就加个lock。intel对lock的定义,就是说加了lock之后,就会自动锁掉一块内存区域,然后同一时间只有一个处理器可以读写这块内存区域,其他处理器就不行了。

 

CAS其实有3个缺点:

 

1、ABA问题:如果某个值一开始是A,后来变成了B,然后又变成了A,你本来期望的是值如果是第一个A才会设置新值,结果第二个A一比较也ok,也设置了新值,跟期望是不符合的。所以atomic包里有AtomicStampedReference类,就是会比较两个值的引用是否一致,如果一致,才会设置新值

 

假设一开始变量i = 1,你先获取这个i的值是1,然后累加了1,变成了2

 

但是在此期间,别的线程将i -> 1 -> 2 -> 3 -> 1

 

这个期间,这个值是被人改过的,只不过最后将这个值改成了跟你最早看到的值一样的值

结果你后来去compareAndSet的时候,会发现这个i还是1,就将它设置成了2,就设置成功了

 

说实话,用AtomicInteger,常见的是计数,所以说一般是不断累加的,所以ABA问题比较少见

 

2、无限循环问题:大家看源码就知道Atomic类设置值的时候会进入一个无限循环,只要不成功,就不停循环再次尝试,这个在高并发修改一个值的时候其实挺常见的,比如你用AtomicInteger在内存里搞一个原子变量,然后高并发下,多线程频繁修改,其实可能会导致这个compareAndSet()里要循环N次才设置成功,所以还是要考虑到的。

 

3、多变量原子问题:一般的AtomicInteger,只能保证一个变量的原子性,但是如果多个变量呢?你可以用AtomicReference,这个是封装自定义对象的,多个变量可以放一个自定义对象里,然后他会检查这个对象的引用是不是一个。

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值