AtomicInteger 中的“Compare And Set”是如何工作的

2022-09-01 11:57:55

AtomicInteger使用两个概念:CAS和变量。volatile

使用变量可确保当前值对所有线程都可见,并且不会被缓存。volatile

但是我对CAS(比较和集合)概念感到困惑,下面解释如下:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
 }

我的问题是,什么回报?该值不会更新吗?在这种情况下,当线程执行以下情况时会发生什么:if(compareAndSet(current, next)false

private AtomicInteger count = new AtomicInteger();
count.incrementAndGet();

答案 1

原子对象利用比较和交换机制使它们成为原子对象 - 即可以保证该值符合指定并且现在处于新值。

您发布的代码不断尝试将当前值设置为比以前多一个值。请记住,另一个线程也可能执行了 a,并且也正在尝试设置它。如果两个线程相互争用以更改值,则其中一个增量可能会失败。get

请考虑以下情形:

  1. 线程 1 调用并获取值 。get1
  2. 线程 1 计算为 。next2
  3. 线程 2 调用并获取值 。get1
  4. 线程 2 计算为 。next2
  5. 两个线程都尝试写入该值。

现在由于原子 - 只有一个线程会成功,另一个线程将从 接收并再次运行。falsecompareAndSet

如果不使用此机制,则两个线程都有可能递增该值,从而导致实际只执行一个递增。

令人困惑的无限循环只有在许多线程同时写入变量时才会真正循环。在非常重的负载下,它可能会循环几次,但它应该很快完成。for(;;)


答案 2

for (;;)是一个无限循环,因此它将重试尝试。


推荐