1

非常に奇妙なエラーが発生します。次のコードがあります。

while (true) {
    System.out.println(model.getLightState());
    if (model.getLightState() == 1) {
        System.out.println("Entered..");
        view.driveThroughJunction();
        break;
    }
}

これで、私のプログラムは、ライトの状態が「1」に変化したときに if ステートメントに入り、正常なコードを実行します。しかし、これはwhileループに入った後にその出力ステートメントがある場合にのみ機能します。私はそれが奇妙だと思います。「sysout」行は if ステートメントに何らかの影響を与えますか? どうやら上記の場合はそうです。

これがなぜなのかについてのアイデアはありますか?

編集:

(in the model class)
public final byte getLightState() {
    return lightChanger.getLightValue();
}

(in lightchanger class)
public byte getLightValue() {
    return light.getState();
}

(in the light class)
public final byte getState() {
    return this.state;
}
4

2 に答える 2

5

可視性の問題につながる同期の問題があります。複数のスレッドで共有される変数を読み書きするときに同期が使用されない場合、1 つのスレッドによって書き込まれた値が他のスレッドから見えるという保証はありません。

それを修正するには、次のいずれかを行う必要があります。

  • stateフィールドを作るvolatile
  • stateフィールドタイプをに変更しますAtomicInteger
  • もちろん、毎回同じロックを使用して、stateフィールドへのすべてのアクセスを(キーワードを使用して)同期します。synchronized

sysout 呼び出しは、レジスタの状態をメイン メモリにフラッシュする何らかのメソッドを内部的に呼び出すため (たとえば、volatile フィールドに書き込むか、同期メソッドを呼び出すことによって)、値を表示します。

于 2012-11-25T17:17:28.717 に答える
2

モデル インスタンスをvolatileとして宣言する必要があります。

Java の Volatile キーワードは、この変数の値をキャッシュせず、常にメイン メモリから読み取る Java コンパイラとスレッドへのインジケータとして使用されます。したがって、実装によって読み取りおよび書き込み操作がアトミックである変数を共有したい場合は、それらを volatile 変数として宣言する必要があります。

詳細: http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2DFw4l8AW

あなたのコメントから、複数のスレッドがモデルの同じインスタンスにアクセスし、モデルの同じインスタンスで読み取り/書き込みを実行していることは明らかです。揮発性スレッドがないと、モデル インスタンスの値がキャッシュされるため、ダーティ リードになってしまいます。System.out.println読み取り/書き込み操作が発生すると(出力書き込みのため)少し遅れるため、スレッドはキャッシュされた値をメインメモリから更新できます。

于 2012-11-25T17:21:35.597 に答える