我正在学习“Java Concurrency in Practice'
”中的多线程编程有一篇文章说,即使看起来无害的增量操作也不是线程安全的,因为它包含三种不同的操作......读取,修改和写入。
class A {
private void int c;
public void increment() {
++c;
}
}
因此增量语句不是原子的,因此不是线程安全的。
我的问题是,如果一个环境真的是并发的(即多个线程能够完全同时执行它们的程序语句)那么一个真正原子的语句也不能是线程安全的,因为多个线程可以读取相同的价值。 那么如何让一个原子语句有助于在并发环境中实现线程安全呢?
答案 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
(或全局)资源。如果值是线程本地的,那么您不需要考虑原子性。