当不同的线程对相同的数据有不同映像时,就发生了内存一致性错误。内存不一致错误的起因很复杂,超出了本课程的范围。好在程序员不需要对它的原因有详细的了解。我们只需要知道避免它的策略即可。
避免内存不一致性错误的关键是了解happens-before关系。这个关键能够简单地保证一个语句修改的内存对另一个语句是可见的。假设有一个int元素已经被定义和初始化了。
int counter = 0
这个counter域在两个线程A,B之间共享。假设A线程对counter进行了增加操作,counter++;然后不一会,线程B将counter打印出来,System.out.println(counter);
如果这两个语句处于同一个线程中,那假设打印出来的结果是1,是没有任何问题的。然而如果这两条语句处于两个分开的线程中,打印出来的结果会是0,因为没有任何保证说明线程A对counter的改变能对线程B可见——除非程序员已经在两个语句之间建立了一个happens-before机制。
有很多种方法来建立happens-before关系。其中的一个是使用同步,这会在接下来的章节中讲到。
我们已经见过两种能够建立happens-before关系的机制了。
- 当一个语句调用Thread.start,每个和当前线程有happens-before关系的语句,也会和新建立的线程有happens-before关系。新建代码的部分对新的线程可见。
- 当一个线程终止,并导致另一个线程使用Thread.join返回,那么被终止线程执行的语句都和成功join操作之后的所有语句有happend-before的关系。
网友评论