The Java™ Tutorials-Concurrency:Thread Interferenceスレッド競合


The Java™ Tutorials-Concurrency:Thread Interferenceスレッド競合
原文住所:https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html
キー(Key)
スレッド競合の原因:同時環境における非原子操作による結果不確実性全文翻訳
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を減算する.しかしながら、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:
Retrieve the current value of c.
Increment the retrieved value by 1.
Store the incremented value back in c.
Counterインスタンスに対する操作は、cに対する操作がすべて個別で簡単な文であるため、インタリーブすることは不可能であるように見えます.しかしながら、JVMは、単純な文でも複数のステップに翻訳することができる.JVMがどのような具体的なステップを行ったのかを検証するのではなく、簡単なc++式が3つのステップに分解できることを知るだけで十分です.
cの値を再取得
取得した値にを加算
新しい値をcに戻してへ
The expression c– can be decomposed the same way, except that the second step decrements instead of increments. c--式も同様のルールで分解されますが、2ステップ目は加算を減算に変更します.
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:
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.
スレッドAがincrementを呼び出し、このときスレッドBもdecrementを呼び出したとする.cの初期値が0の場合、それらが交差して行う操作は、次のリズムに従って行われる可能性があります.
スレッドA:cの値を取得する
スレッドB:cの値を取得する
スレッドA:取得したc値に1を加算する.結果は1 スレッドB:取得したc値を1つ減算する.結果は-1スレッドA:結果をcに戻す;c現在は1 スレッドB:結果をcに戻す;c現在-1Thread 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の結果に上書きされる.このインタリーブの順序はその中の1つの可能性にすぎない.場合によっては、スレッドBの結果が失われたり、エラーが発生したりしない可能性があります.これは予見不可能であるため,スレッド競合の欠陥の検出と修復は困難である.