我正在遍历addAndGet类中AtomicInteger方法的Java(Java 6)源代码。

相应的代码如下:

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

compareAndSet方法调用一个本地方法来执行分配。
主要有两个问题:
  • 无限循环有何帮助?
  • 在什么情况下,如果“
    (compareAndSet(current,next))“条件可能返回false?
    在这种情况下,代码可能会陷入无限循环。如果是
    保证compareAndSet将始终返回“true”,然后可以
    我们不会完全取消这张支票吗?
  • decrementAndGetgetAndDecrementgetAndAdd方法也有类似的疑问。

    最佳答案

    无限循环有何帮助?

    这意味着:重试直到成功。
    如果没有循环,则第一次可能不会成功(请参阅下文)。

    在“if(compareAndSet(current,next))”条件下可能返回false的情况是什么?

    如果两个线程试图同时修改该值,则会发生这种情况。其中一个将首先到达那里。另一个将失败。

    想象两个线程(A和B)试图从5递增到6

    A: int current = get();  // current = 5
    B: int current = get();  // current = 5
    B: int next = current + delta;  // next = 6
    B: if (compareAndSet(current, next))  // OK
              return next;
    A: int next = current + delta;  // next = 6
    A: if (compareAndSet(current, next))
        // fails, because "current" is still 5
        // and that does not match the value which has been changed to 6 by B
    

    请注意,此类的重点是避免锁定。因此,您具有这种“乐观的货币控制”:只需假设没有其他人同时在处理数据,并且如果发现这是错误的,请回滚并重试。

    在这种情况下,代码可能会陷入无限循环

    并不是的。对于每一个对值有作用的线程,它只能失败一次。

    在第二次迭代中从上方线程A:
    A: int current = get();  => current now 6
    A: int next = current + delta;  => next = 7
    A: if (compareAndSet(current, next))  => now OK
    

    可以想象,如果其他线程不断地更新该值,那么一个线程将永远等待,直到那时。为了避免这种情况,您需要对“公平”进行一些定义(并发包中的其他一些工具也支持)。

    08-27 02:26