AtomicInteger incrementAndGet原子性

Tom*_*myQ 7 java atomicity java.util.concurrent

根据文档,AtomicInteger.incrementAndGet()是原子的.但是,在下面的源代码中,如果另一个线程在"返回下一个"之前交错怎么办?那么"下一步"会不正确吗?

public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
          return next;
    }
}
Run Code Online (Sandbox Code Playgroud)

Old*_*eon 6

如果另一个线程交错,那么它也会成功地向该值添加一个.

原子性保证您的增量发生,如果两个线程尝试增量,那么最终两个线程将成功(并且增加2).它不保证任何未来的价值.

在您的方案中,它看起来像以下代码:

public final long incrementAndGet() {
    for (;;) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next)) {
            // Other thread.
            for (;;) {
                long current2 = get();
                long next2 = current2 + 1;
                if (compareAndSet(current2, next2)) {
                    return next2;
                }
            }
            return next;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

即每个线程获得它自己递增的值.


rdl*_*pes 2

什么是“正确”?

下一个值不是 AtomicInteger 的当前值,而是增加“当前”值所得到的值。

让我们假设以下模拟(这样,“线程 2”在“返回下一个”之前交错“线程 1”)

i = 10
Thread 1
calling 'j = incrementAndGet(i)'
computing incrementAndGet(i) by Thread 1
now i = 11

Thread 2
calling 'm = incrementAndGet(i)'
computing incrementAndGet(i) by Thread 2
now i = 12 

Thread 1
now j = 11 

Thread 2
now m = 12 

Thread 3
calling 'n = incrementAndGet(i)'
// Hey! It should be only with Thread 1 and 2!
now i = 13 and n = 13
Run Code Online (Sandbox Code Playgroud)

事实上,incrementAndGet 是原子的。为什么?因为线程1在我10岁的时候调用了incrementAndGet,得到了11。而线程2在我11岁的时候调用了incrementAndGet,得到了12。我是否会被改变并不重要。在incrementAndGet之后,调用者得到增量后的结果值。