Javaのスレッド間の不整合を防ぐためにキーワードを使用することについてはかなりしっかりと理解していると思いますが、そのsynchronized
キーワードを使用しないとどうなるかを完全には理解していません。
たとえば、2つのスレッドによってアクセス/変更されたフィールドがあるとします。
private String sharedString = "";
class OneThread extends Thread {
private Boolean mRunning = false;
public OneThread() {}
public synchronized setRunning(Boolean b) {
mRunning = b;
}
@Override
public void run() {
while (mRunning) {
// read or write to shared string
sharedString = "text from thread 1";
System.out.println("String seen from thread 1: " + sharedString);
super.run();
}
}
}
class AnotherThread extends Thread {
private Boolean mRunning = false;
public AnotherThread() {}
public synchronized setRunning(Boolean b) {
mRunning = b;
}
@Override
public void run() {
while (mRunning) {
// read or write to shared string
sharedString = "text from thread 2";
System.out.println("String seen from thread 2: " + sharedString);
super.run();
}
}
}
これらのスレッドは両方ともsharedString
、synchronizedキーワードを使用せずにフィールドにアクセスして変更しているため、不整合が予想されます。私が疑問に思っているのは、実際に何が起こっているのかということです。デバッグ中に、このような状況で両方のスレッドを注意深く調べたところ、1つのスレッドが一時停止している間でも、その状態が「スティッキー」になる可能性があることに気付きました。
上記の例のために、両方のスレッドがデバッガーで一時停止されていると仮定します。スレッドの1つをステップスルーし、もう1つを一時停止したままにすると、シングルスレッドアプリケーションのように動作することが期待されます。ただし、フィールドを変更した直後に、フィールドにアクセスする次の行で「間違った」値(変更されたばかりの値と一致しない値)が取得されることがよくあります。
このコードは良くないことは知っていますが、マルチスレッドアプリケーションが適切に実装されていない場合に仮想マシンで実際に何が起こるかについての洞察を誰かが提供してくれることを期待しているので、質問をしています。フィールド修正の試みが失敗したスレッドは、まったく効果がありますか?
マルチスレッドコードの実装が不十分だった後、単に「未定義」の動作の領域にあり、この動作について学習する価値がない場合、私はそれで大丈夫です。デバッガーで観察します。