AtomicInteger incrementAndGet原子性

时间:2014-03-31 07:52:07

标签: java java.util.concurrent atomicity

根据文档,

AtomicInteger.incrementAndGet()是原子的。但是,在下面的源代码中,如果另一个线程在&#34之前交错怎么办?返回下一个"? "接着"那会不正确吗?

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

6 个答案:

答案 0 :(得分:6)

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

Atomicity保证你的增量发生,如果两个线程尝试增加,那么最终两个线程将成功(并且增加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;
        }
    }
}

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

答案 1 :(得分:3)

每次调用都会正确递增值,因此唯一可能影响的是返回值。

该函数的语义是它不返回整数的当前值,但调用incrementAndGet()的值增加了整数(更新后的值) 。

让我举个例子:

public MyClass {
    private AtomicInteger counter;

    public int getNextUniqueIndex() {
        return counter.getAndIncrement();
    }
}

现在,如果你调用getNextUniqueIndex(),它将始终返回一个唯一值,而不管调用线程或线程交错。这是因为从next的实现返回的incrementAndGet()的值是指此incrementAndGet()调用更新的值。

答案 2 :(得分:2)

什么是"正确"?

下一个值不是AtomicInteger的当前值,而是通过递增"当前"得到的值。值。

让我们假设以下模拟(以这种方式,"线程2"交错"线程1"就在&#34之前;返回下一个")

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

确实,incrementAndGet是原子的。为什么?因为当我10岁时,线程1调用incrementAndGet并且得到11.当我11岁时,线程2调用incrementAndGet并且得到12.如果我将被更改并不重要。在incrementAndGet之后,调用者在增量后得到结果值。

答案 3 :(得分:2)

如果在compareAndSet之后然后是,则incrementAndGet可能会向其他某个线程传递更高的值。但是,在返回后,它将保持。该值将增加2(正确),并且两个线程都将获得不同的值。

这形成了“正确”的语义。对于平行线程,没有完美的时间同步性。

答案 4 :(得分:2)

compareAndSet方法保证更新的原子性,但不能保证返回的值是'latest'。 incrementAndGet仅保证1)值以原子方式递增,2)得到该增量的结果。成功增量之前(或之后)发生的事情与当前Thread无关。

答案 5 :(得分:1)

incrementAndGet正在使用compareAndSet,它正在使用unsafe.compareAndSwapInt。 此方法如果Java变量当前保持预期的整数,则将其原子更新为给定的整数。

因此,当两个线程尝试递增该值时,如果JVM相同则JVM将自动比较现有值,则增量将成功,否则它将不会成功。