Counter类对象的操作貌似不可能出现这种“交错”,因为其中的两个关于c的操作都很简单,只有一条语句。然而,即使是一条语句也是会被VM翻译成多个步骤的。在这里,我们不深究VM具体上上面的操作翻译成了什么样的步骤。只需要知道即使简单的c++这样的表达式也是会被翻译成三个步骤的:
1. 获取c的当前值。
2. 对其当前值加1。
3. 将增加后的值存储到c中。
表达式c--也是会被按照同样的方式进行翻译,只不过第二步变成了减1,而不是加1。
假定线程A中调用increment方法,线程B中调用decrement方法,而调用时间基本上相同。如果c的初始值为0,那么这两个操作的“交错”顺序可能如下:
1. 线程A:获取c的值。
2. 线程B:获取c的值。
3. 线程A:对获取到的值加1;其结果是1。
4. 线程B:对获取到的值减1;其结果是-1。
5. 线程A:将结果存储到c中;此时c的值是1。
6. 线程B:将结果存储到c中;此时c的值是-1。
这样线程A计算的值就丢失了,也就是被线程B的值覆盖了。上面的这种“交错”只是一种可能性。在不同的系统环境中,有可能是B线程的结果丢失了,或者是根本就不会出现错误。由于这种“交错”是不可预测的,线程间相互干扰造成的缺陷是很难定位和修改的。