Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
在编程中,atomic (原子) 动作是一次性完全发生的动作。原子动作不能在中间停止:它要么完全发生,要么根本不发生。在动作完成之前,原子动作的副作用是不可见的。
我们已经看到增量表达式,例如 c++
,不属于原子动作。即使非常简单的表达式也可以定义为可以分解为其他操作的复杂操作。但是,有一些动作可以指定是原子操作:
long
和 double
之外的所有类型)是原子的。volatile
的变量(包括 long
和 double
变量)是原子的。原子动作不能交错,因此可以使用它们而不必担心线程干扰。但是,这并不能消除所有同步原子操作的需要,因为仍然可能存在内存一致性错误。使用 volatile
变量可以降低内存一致性错误的风险,因为对 volatile
变量的任何写入都会与之后读取同一变量的操作建立 happens-before 关系。这意味着对 volatile
变量的更改始终对其他线程可见。更重要的是,它还意味着当线程读取 volatile
变量时,它不仅会看到 volatile
的最新更改,还会看到导致其更改的代码的副作用。
使用简单的原子变量访问比通过同步代码访问这些变量更有效,但程序员需要更加小心以避免内存一致性错误。额外的努力是否值得取决于应用程序的大小和复杂性。
java.util.concurrent
包中的某些类提供了不依赖于同步的原子方法。我们将在 High Level Concurrency Objects 一节中讨论它们。