参考答案
1. CAS的作用
它可以解决多线程并发安全的问题,以前我们对一些多线程操作的代码都是使用synchronize关键字,来保证线程安全的问题。现在,我们将cas放入到多线程环境中,看看它是如何解决的。
假设:
有A、B两个线程,线程B比A快了那么0.00000001s,它们同时执行一个int值value自增的代码,且同时获取了当前的value。
线程B先执行,线程B执行cas操作之后,发现当前值和预期值相符,就执行了自增操作。此时,这个value = value + 1。
然后A开始执行,A也执行了cas操作,但此时value的值和它当时取到的值已经不一样了,所以此次操作失败,重新取值然后比较成功,然后将value值更新,这样两个线程进入,value值自增了两次,符合我们的预期。
2. CAS在JDK中的应用
Java从jdk1.5开始,引入并使用CAS,Java中的Atomic系列就是使用cas实现的。
接下来,用AtomicInteger类来看看Java是如何实现的。
进入到AtomicInteger类,我们发现它使用volatile声明了一个变量,volatile声明的这个变量是易变的,当线程拿到这个值并且更新之后,还要将更新后的值同步到主内存里边,供之后的线程调用。
前面了解了volatile的特性,再来看看它是如何实现自增的。
AtomicInteger有一个incrementAndGet的自增方法。
在一个循环里,每次去获取当前的值current,将当前值current+1赋值给next,再将current和next放到compareAndSet中进行比较。如果返回true,那么就return next的值;如果失败,那么继续进行上述操作。
这里就使用了cas操作。
再来看compareAndSet是不是也使用了CAS,下面进入compareAndSet方法中一探究竟。
这个compareAndSet方法有两个参数,分别叫expect和update,从字面上理解就是预期的值和更新的值。
这里边调用了一个compareAndSwapInt的方法,有四个参数,分别是当前的值this、valueOffset、预期值expect、更新的值update。
其中,expect和update是通过参数传过来的,梳理下this当前值和预期值expect,也就是current进行比较。如果相等,就把值更新为update也就是next。
此次自增操作就完成了。
以上,是Java面试题【CAS在JDK中有哪些应用】的参考答案。
输出,是最好的学习方法。
欢迎在评论区留下你的问题、笔记或知识点补充~
—end—
拓展阅读: