理解Java原子性访问
在编程中,一个原子动作是一个有效地同时发生的动作。一个原子动作不能中途停止:它要么完全发生,要么根本不发生。在动作完成之前,原子动作的任何副作用都是不可见的。 我们已经看到,一个增量表达式,如 a++ ,并不能描述一个原子动作。即使是非常简单的表达式也可以定义复杂的动作,这些动作可以分解为其他动作。然而,你可以指定一些动作是原子的: 对于引用变量和大多数原始变量( 除了 long 和 double 以外的所有类型 )的读和写都是原子性的。 对于所有声明为 volatile 的变量(包括 long 变量和 double 变量),读和写都是原子性的。 原子操作不能交错,所以可以不用担心线程干扰。然而,这并不能消除所有同步原子动作的需要,因为内存一致性错误仍然可能发生。使用 volatile 变量可以降低内存一致性错误的风险,因为对 volatile 变量的任何写都会与该变量的后续读建立一个发生在前的关系。这意味着对 volatile 变量的更改总是对其他线程可见。更重要的是,这也意味着当一个线程读取一个 volatile 变量时,它不仅能看到 volatile 变量的最新变化,还能看到导致该变化的代码的副作用。 使用简单的原子变量访问比通过同步代码访问这些变量更有效率,但需要程序员更加小心,以避免内存一致性错误。额外的努力是否值得,取决于应用程序的大小和复杂程度。