在编程中,一个原子操作是指能一次发生的动作。一次原子操作不能被中途打断:它要么完全执行,要么根本不执行。原子操作的副作用必须在它结束之后,才能看到。
我们已经看到了一个自增操作,像是c++,不能被称作是一个原子操作。即使是翻唱简单的表示式,也能被拆解为若干动作。不过,以下的动作你可以称其为原子的:
- 对引用变量和大部分基础变量(除了long和double),读或写操作是原子的。
- 被声明成volatile的变量的读和写操作都是原子的,包括long和double。
原子操作互相不能重叠,因此无需担心它们会有线程混淆。但是,这并不意味着原子操作就不需要同步,因为内存一致性的问题仍然存在。使用volatile关键字可以减少内存不一致性错误的风险,因为写入任何以volatile修饰的变量,都会和之后对该变量的读建立起一个happens-before的关系。这意味着,对volatile变量的改动对其他线程也是可见的,它不仅能看到最新的变化,而且能看到由于这个变化给整个代码带来的影响。
与通过同步代码来进入这些变量相比,使用简单的原子变量准入是一个更有效的方法,但是后者需要开发人员更加小心地防止内存一致性问题。这种额外的努力是否值得取决于应用的大小和复杂性。
java.util.concurrent包中的一些类提供了不依赖于同步的原子方法。我们会在高级并发对象章节中学到。