【问题标题】:Use of infinite loop in AtomicInteger.addAndGet(int)在 AtomicInteger.addAndGet(int) 中使用无限循环
【发布时间】:2016-07-07 18:27:05
【问题描述】:

在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;
    }
}

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

【问题讨论】:

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


    【解决方案1】:

    这是CAS loop 的经典示例。 compare-and-set 是一个原子操作,它有直接的硬件支持(通常有一些 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;
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        这里的动机是你会最终return next。 意味着条件:

        if (compareAndSet(current, next))
        

        在某些迭代中将是true。不知道它什么时候会发生,所以这就是为什么你需要循环直到它发生。如果你查看compareAndSet的代码,你会看到它在成功时返回true,并且你无法知道它在第一次尝试时会成功:

        如果成功则返回真。 False return表示实际值不等于期望值。

        【讨论】:

        • 看起来很简单,但它会阻止执行,直到 addAndGet 返回。是否有替代 compareAndSet 该块的执行,因此不需要 for(;;)?
        • @TagirValeev 我的错,我现在更新解释
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-23
        • 1970-01-01
        • 2023-03-18
        • 1970-01-01
        • 2018-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多