增量运算的原子性

时间:2015-07-25 05:03:50

标签: java concurrency atomic

我正在学习“Java Concurrency in Practice'

”中的多线程编程

有一篇文章说,即使看起来无害的增量操作也不是线程安全的,因为它包含三种不同的操作......读取,修改和写入。

class A {
  private void int c;

  public void increment() {
    ++c;
  }
}

因此增量语句不是原子的,因此不是线程安全的。

我的问题是,如果一个环境真的是并发的(即多个线程能够完全同时执行它们的程序语句)那么一个真正原子的语句也不能是线程安全的,因为多个线程可以读取相同的价值。 那么如何让一个原子语句有助于在并发环境中实现线程安全呢?

2 个答案:

答案 0 :(得分:2)

在修改状态时不存在真正的并发性。

This post对并发和并行有一些很好的描述。

正如@RitchieHindle在该帖子所述:

  

并发是指两个任务可以在重叠的时间段内启动,运行和完成。它并不一定意味着它们都会在同一时刻运行。例如。在单核机器上进行多任务处理。

作为一个例子,非原子操作的危险在于一个线程可能读取该值,另一个线程可能会修改该值,然后原始线程可能会修改并写入该值(从而否定第二个线程所做的修改) 。

在原子操作过程中,原子操作不允许其他操作访问状态。例如,如果增量运算符是原子的,它将读取,修改和写入,而这些操作发生时没有任何其他线程可以访问该变量状态。

答案 1 :(得分:0)

您可以使用AtomicInteger。链接的Javadoc(部分)说 int值可以原子更新AtomicInteger还实现了addAndGet(int),其中以原子方式将给定值添加到当前值

private AtomicInteger ai = new AtomicInteger(1); // <-- or another initial value
public int increment() {
    return ai.addAndGet(1); // <-- or another increment value
}

这可以(例如)允许您保证多个线程的写入顺序一致性。考虑一下,ai可能代表(或包含)某些static(或全局)资源。如果值是线程本地的,那么您不需要考虑原子性。