自增操作的原子性
Atomicity of increment operation
我正在学习 'Java Concurrency in Practice' 的多线程编程。
书中曾说过,即使是看似无害的增量操作也不是线程安全的,因为它由三种不同的操作组成...读取、修改和写入。
class A {
private void int c;
public void increment() {
++c;
}
}
所以增量语句不是原子的,因此不是线程安全的。
我的问题是,如果一个环境真的是并发的(即多个线程能够完全同时执行它们的程序语句)那么一个真正原子的语句也不能是线程安全的,因为多个线程可以读取相同的值。
那么拥有原子语句如何有助于在并发环境中实现线程安全?
真正的并发在修改状态时是不存在的。
This post 对并发和并行有一些很好的描述。
正如@RitchieHindle 所说 post:
Concurrency is when two tasks can start, run, and complete in overlapping time periods. It doesn't necessarily mean they'll ever both be running at the same instant. Eg. multitasking on a single-core machine.
举个例子,非原子操作的危险在于一个线程可能读取值,另一个线程可能修改值,然后原始线程可能修改并写入值(从而否定第二个线程的修改做过)。
原子操作不允许其他操作在原子操作中间访问状态。例如,如果增量运算符是原子的,那么在这些操作发生时,它会读取、修改和写入,而无需任何其他线程访问该变量状态。
您可以使用 AtomicInteger
. The linked Javadoc says (in part) that it is an int
value that may be updated atomically. AtomicInteger
also implements 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
(或全局)资源。如果一个值是线程局部的,那么你不需要考虑原子性。
我正在学习 'Java Concurrency in Practice' 的多线程编程。
书中曾说过,即使是看似无害的增量操作也不是线程安全的,因为它由三种不同的操作组成...读取、修改和写入。
class A {
private void int c;
public void increment() {
++c;
}
}
所以增量语句不是原子的,因此不是线程安全的。
我的问题是,如果一个环境真的是并发的(即多个线程能够完全同时执行它们的程序语句)那么一个真正原子的语句也不能是线程安全的,因为多个线程可以读取相同的值。 那么拥有原子语句如何有助于在并发环境中实现线程安全?
真正的并发在修改状态时是不存在的。
This post 对并发和并行有一些很好的描述。
正如@RitchieHindle 所说 post:
Concurrency is when two tasks can start, run, and complete in overlapping time periods. It doesn't necessarily mean they'll ever both be running at the same instant. Eg. multitasking on a single-core machine.
举个例子,非原子操作的危险在于一个线程可能读取值,另一个线程可能修改值,然后原始线程可能修改并写入值(从而否定第二个线程的修改做过)。
原子操作不允许其他操作在原子操作中间访问状态。例如,如果增量运算符是原子的,那么在这些操作发生时,它会读取、修改和写入,而无需任何其他线程访问该变量状态。
您可以使用 AtomicInteger
. The linked Javadoc says (in part) that it is an int
value that may be updated atomically. AtomicInteger
also implements 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
(或全局)资源。如果一个值是线程局部的,那么你不需要考虑原子性。