在AtomicInteger类中实现addAndGet

时间:2013-07-17 05:43:26

标签: java synchronization atomic java-6

我正在查看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方法调用本机方法来执行赋值。 主要有两个问题:

  1. 无限循环如何帮助?
  2. 可能是什么情景,“if (compareAndSet(current,next))“条件可能返回false?In 在这种情况下,代码可能会遇到无限循环。如果是 保证compareAndSet总是返回“true”,然后才可以 我们不完全取消这项检查吗?
  3. 类似的疑问也适用于decrementAndGetgetAndDecrementgetAndAdd方法。

1 个答案:

答案 0 :(得分:9)

  

无限循环如何帮助?

这意味着:重试直到它起作用。 没有循环,第一次可能不会成功(见下文)。

  

“if(compareAndSet(当前,下一个))”条件可能返回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

如果其他线程不断更新该值,您可以想象最终会有一个线程永远等待,但只有这样。为了避免这种情况,你需要一些“公平”的定义(并发包中的一些其他工具支持)。