在AtomicInteger.addAndGet(int)

时间:2016-03-21 09:54:37

标签: java for-loop integer infinite-loop atomic

在Java的包中java.util.concurrent.atomic AtomicInteger类有一个方法addAndGet(int)

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

为什么它在这里使用无限循环来设置值?

3 个答案:

答案 0 :(得分:5)

这是CAS loop的经典示例。比较和设置是一个原子操作,它具有直接的硬件支持(通常它背后有一些CPU指令)。它仅在当前值等于预期值时原子地更新给定变量,并且如果一切都成功则返回true。通常这个循环只执行一次。但是在竞争中(当其他线程尝试更新相同的值时),可能在通过get()读取当前值并通过compareAndSet更新它之后,另一个线程设法更新它。在这种情况下,整个过程将重试,直至成功。

在这里使用无限循环只是风格问题。它可以使用普通do-while循环重写:

public final int addAndGet(int delta) {
    int current, next;
    do {
        current = get();
        next = current + delta;
    } while (!compareAndSet(current, next));
    return next;
}

答案 1 :(得分:2)

compareAndSet或仅CAS与非阻塞线程安全算法有关。在addAndGet的情况下,增量操作是获取旧值,将其转换为新值并使用CAS 尝试设置新值,如果current不是&#39}。在增量期间修改。如果CAS失败,则会重试,直到成功为止。在没有极端争用的情况下,这种策略是有效的。

答案 2 :(得分:0)

这里的动机是最终 TEST。 意思是条件:

return next

在某次迭代中会if (compareAndSet(current, next)) 。目前还不知道它究竟会发生什么,所以这就是你需要循环直到它的原因。如果您查看compareAndSet的代码,您会看到它在成功时返回true,并且您无法在第一次尝试时知道它会成功:

  

如果成功则返回true。错误返回表示实际值不等于预期值。