在AtomicInteger类中实现addAndGet

我正在浏览AtomicInteger类中的addAndGet方法的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? 在这种情况下,代码可能会遇到无限循环。 如果保证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 

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