根据documentation.However,AtomicInteger.incrementAndGet()是原子的,在下面的源代码中,如果另一个线程在“返回下一个”之前交错,该怎么办?“下一步”是不正确的吗?
public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}发布于 2014-03-31 15:59:37
如果另一个线程是交错的,那么它也会成功地将值加1。
原子性保证您的增量发生,并且如果两个线程尝试增量,那么最终将有两个线程成功(并且递增两个)。它不能保证任何关于未来价值的东西。
在您的场景中,它看起来像下面的代码:
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;
}
}
}也就是说,每个线程都有自己的增量值。
发布于 2014-03-31 15:59:33
每次调用都会正确地递增该值,因此它唯一可能影响的就是返回值。
该函数的语义是,它不返回整数的当前值,而是调用incrementAndGet()将整数增加到的值(更新值)。
让我给你举个例子:
public MyClass {
private AtomicInteger counter;
public int getNextUniqueIndex() {
return counter.getAndIncrement();
}
}现在,如果您调用getNextUniqueIndex(),它将始终返回一个惟一的值,而不管调用线程或线程交错。这是因为从incrementAndGet()的实现返回的next的值引用了这次incrementAndGet()调用更新的值。
发布于 2014-03-31 15:58:19
什么是“正确”?
下一个值不是AtomicInteger的当前值,而是" current“值递增后的值。
让我们假设下面的模拟(以这种方式,“线程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事实上,incrementAndGet是原子的。为什么?因为线程1在我10岁的时候调用了incrementAndGet,得到了11。线程2在我11岁的时候调用了incrementAndGet,得到了12。在incrementAndGet之后,调用者获得递增后的结果值。
https://stackoverflow.com/questions/22756225
复制相似问题