爱游戏全站app官网入口-爱游戏官网

2020-爱游戏全站app官网入口

2023-08-09,,

福哥答案2020-10-16:#福大大架构师每日一题#

简单回答:
cmpxchg原子指令。aba,循环开销大,一个共享变量。

[知乎](https://www.zhihu.com/question/425863643/answer/1527001400)
[csdn](https://blog.csdn.net/weixin_37598682/article/details/81285176)

中级回答:
cas 底层实现主要依靠的cmpxchg是 cpu 指令级的操作,只有一步原子操作,所以非常快。它本身的性能瓶颈主要来自于:多核环境下,上次执行 cas 更新的 cpu 和本次 执行 cas 更新的 cpu 不是同一个 cpu。例如:
1.cpu 1 执行了某个内存地址 x 的cas更新,那么 x 对应的内存会被载入 cpu 1 的高速缓存中。
2.这时候 cpu 2 需要 cas 更新 x,发现 cpu 2 的高速缓存中没有 x。
3.查询总线,发现 cpu 1 有。
4.cpu 1 将 x 发送给 cpu 2,并且刷新自己高速缓存中的缓存线。
5.cpu 2 可以执行 cas 更新了。

产生的问题以及爱游戏官网的解决方案:
1.aba问题。因为cas需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是a,变成了b,又变成了a,那么使用cas进行检查时会发现它的值没有发生变化,但是实际上却变化了。aba问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么a-b-a 就会变成1a-2b-3a。

从java1.5开始jdk的atomic包里提供了一个类atomicstampedreference来解决aba问题。这个类的compareandset方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

atomicmarkablereference的实现原理与atomicstampedreference类似,这里不再介绍。到此,我们也明白了如果要完全杜绝aba问题的发生,我们应该使用atomicstampedreference原子类更新对象,而对于atomicmarkablereference来说只能减少aba问题的发生概率,并不能杜绝。

2.循环时间长开销大。自旋cas如果长时间不成功,会给cpu带来非常大的执行开销。如果jvm能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使cpu不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起cpu流水线被清空(cpu pipeline flush),从而提高cpu的执行效率。

3.只能保证一个共享变量的原子操作。当对一个共享变量执行操作时,我们可以使用循环cas的方式来保证原子操作,但是对多个共享变量操作时,循环cas就无法保证操作的原子性,这个时候就可以用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i=2,j=a,合并一下ij=2a,然后用cas来操作ij。从java1.5开始jdk提供了atomicreference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行cas操作。
***
[评论](https://user.qzone.qq.com/3182319461/blog/1602803540)

2020-10-16:cas知道么?底层实现? 会引发?如何解决aba问题?的相关教程结束。

网站地图