1.CPU开销过大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很到的压力。
比如:AtomicInteger当中常用的自增方法incrementAndGet:
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
private volatile int value;
public final int get() {
return value;
}
这段代码是一个无限循环,也就是CAS的自旋,循环体中做了三件事:
- 获取当前值
- 当前值+1,计算出目标值
- 进行CAS操作,如果成功则跳出循环,如果失败则重复上述步骤。
这里需要注意的重点是get方法,这个方法的作用是获取变量的当前值。
如何保证获取的当前值是内存中的最新值?很简单,用volatile关键字来保证(保证线程间的可见性)。
2.不能保证代码块的原子性
CAS机制所保证的知识一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用synchronized了。
3.ABA问题
这是CAS机制最大的问题所在。
关联问题
1>. java语言CAS底层如何实现?
利用unsafe提供的原子性操作方法。
2>.什么是ABA问题?怎么解决?
当一个值从A变成B,又更新回A,普通CAS机制会误判通过检测。
利用版本号比较可以有效解决ABA问题。(小明取钱,刚好妈妈存钱例子)
参考:https://www.sohu.com/a/314272265_120104204
网友评论