The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
Memory consistency errors occur when different threads have inconsistent views of what should be the same data. 内存一致性错误发生在不同线程对相同数据的视图不一致时。The causes of memory consistency errors are complex and beyond the scope of this tutorial. 内存一致性错误的原因很复杂,超出了本教程的范围。Fortunately, the programmer does not need a detailed understanding of these causes. 幸运的是,程序员不需要详细了解这些原因。All that is needed is a strategy for avoiding them.所需要的只是一个避免它们的策略。
The key to avoiding memory consistency errors is understanding the happens-before relationship. 避免内存一致性错误的关键是理解“先发生后发生”关系。This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement. 这种关系只是保证一条特定语句的内存写入对另一条特定语句可见。To see this, consider the following example. 要了解这一点,请考虑下面的示例。Suppose a simple 假设定义并初始化了一个简单的int
field is defined and initialized:int
字段:
int counter = 0;
The counter
field is shared between two threads, A and B. counter
字段在两个线程A和B之间共享。Suppose thread A increments 假设线程是一个递增counter
:counter
:
counter++;
Then, shortly afterwards, thread B prints out 然后,不久之后,线程B打印出counter
:counter
:
System.out.println(counter);
If the two statements had been executed in the same thread, it would be safe to assume that the value printed out would be "1". 如果这两条语句是在同一个线程中执行的,则可以安全地假定打印出的值为“1”。But if the two statements are executed in separate threads, the value printed out might well be "0", because there's no guarantee that thread A's change to 但是,如果这两条语句在不同的线程中执行,那么输出的值很可能是“0”,因为不能保证线程A对的更改对线程B可见除非程序员在这两条语句之间建立了“发生在”关系。counter
will be visible to thread B unless the programmer has established a happens-before relationship between these two statements.
There are several actions that create happens-before relationships. 有几个动作是在关系发生之前创建的。One of them is synchronization, as we will see in the following sections.其中之一是同步,我们将在下面的部分中看到。
We've already seen two actions that create happens-before relationships.我们已经看到了两种在关系发生之前产生的行为。
Thread.start
, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. Thread.start
时,与该语句具有“发生在之前”关系的每个语句与新线程执行的每个语句都具有“发生在之前”关系。Thread.join
in another thread to return, then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join. Thread.join
返回时,终止的线程执行的所有语句都与成功连接后的所有语句具有“发生在之前”关系。For a list of actions that create happens-before relationships, refer to the Summary page of the 有关创建关系之前发生的操作的列表,请参阅java.util.concurrent
package..java.util.concurrent
包的摘要页面。