Thread Interference
Thread Interference
线程冲突
Consider a simple class called Counter
考虑一个称作Counter的类
class Counter {
private int c = 0;
public void increment() {
c++;
}
public void decrement() {
c--;
}
public int value() {
return c;
}
}
Counter is designed so that each invocation of increment will add 1 to c, and each invocation of decrement will subtract 1 from c. However, if a Counter object is referenced from multiple threads, interference between threads may prevent this from happening as expected.
Counter中increment调用一次就会在c上加1,decrement调用一次就会从c减去1.然而如果Counter对象被多个线程引用,线程之间的冲突就会引起意料之外的事情发生。
Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.
当2个操作发生在不同的线程,但是交替操作了同样的数据,冲突就会发生。这表明这2个操作时由多个步骤组成的,并且步骤的顺序重复了。
It might not seem possible for operations on instances of Counter to interleave, since both operations on c are single, simple statements. However, even simple statements can translate to multiple steps by the virtual machine. We won't examine the specific steps the virtual machine takes — it is enough to know that the single expression c++ can be decomposed into three steps:
操作(operations这里值自加或自减)在Counter的实例中交错(interleave交替发生)看起来不可能,因为对c的操作时单一的简单的语句。然而,即使是简单的语句在虚拟机中也会转换成多个步骤。我们不会检测虚拟机执行的详细步骤-不过我们知道c++会分解成下面三个步骤就足够了
Retrieve the current value of c. 取得当前c的值
Increment the retrieved value by 1. 在取得的值上加1
Store the incremented value back in c. 将加1后得到的值存回c
The expression c-- can be decomposed the same way, except that the second step decrements instead of increments.
表达式c--能够以同样的方式分解,除了把第二步的减法代替加法
Suppose Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, their interleaved actions might follow this sequence:
假设线程A调用increment在几乎相同的时间线程B调用decrement。如果c的初始值为0,它们可能会像下面这样的顺序交替执行
Thread A: Retrieve c.
Thread B: Retrieve c.
Thread A: Increment retrieved value; result is 1.
Thread B: Decrement retrieved value; result is -1.
Thread A: Store result in c; c is now 1.
Thread B: Store result in c; c is now -1.
Thread A's result is lost, overwritten by Thread B. This particular interleaving is only one possibility. Under different circumstances it might be Thread B's result that gets lost, or there could be no error at all. Because they are unpredictable, thread interference bugs can be difficult to detect and fix.
线程A的结果丢失了,被线程B重写了。这个特别的交错仅仅只是一种可能。在不同的环境下可能是线程B的结果丢失,或者根本就不会发生错误。以为它们是不 可预测的,线程冲突bugs很难检测和修复。