【问题标题】:Implementation of the addAndGet in AtomicInteger classAtomicInteger 类中 addAndGet 的实现
【发布时间】:2013-07-17 05:43:26
【问题描述】:

我正在查看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. 可能的情况是什么,在这种情况下,“如果 (compareAndSet(current, next))" 条件可能返回 false ? 在这种情况下,代码可能会陷入无限循环。如果是 保证 compareAndSet 将始终返回“true”,然后可以 我们不会完全取消这项检查吗?

decrementAndGetgetAndDecrementgetAndAdd 方法也有类似的疑问。

【问题讨论】:

    标签: java synchronization atomic java-6


    【解决方案1】:

    无限循环有什么帮助?

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

    在哪些情况下,“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
    

    如果其他线程不断更新值,您可能会导致一个线程永远等待,但仅此而已。为避免这种情况,您需要对“公平”进行一些定义(并发包中的一些其他工具支持)。

    【讨论】:

      猜你喜欢
      • 2013-11-14
      • 1970-01-01
      • 2012-06-17
      • 2013-02-15
      • 2011-06-16
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多