1. ホーム
  2. java

[解決済み] != チェックスレッドは安全か?

2022-05-29 20:42:16

質問

のような複合演算は知っています。 i++ はスレッドセーフではありません。 複数の 演算を含むため、スレッドセーフではありません。

しかし、自分自身との参照をチェックすることは、スレッドセーフな操作なのでしょうか?

a != a //is this thread-safe

これをプログラムして、複数のスレッドを使おうとしましたが、失敗しませんでした。私のマシンではレースをシミュレートできなかったようです。

EDITです。

public class TestThreadSafety {
    private Object a = new Object();

    public static void main(String[] args) {

        final TestThreadSafety instance = new TestThreadSafety();

        Thread testingReferenceThread = new Thread(new Runnable() {

            @Override
            public void run() {
                long countOfIterations = 0L;
                while(true){
                    boolean flag = instance.a != instance.a;
                    if(flag)
                        System.out.println(countOfIterations + ":" + flag);

                    countOfIterations++;
                }
            }
        });

        Thread updatingReferenceThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while(true){
                    instance.a = new Object();
                }
            }
        });

        testingReferenceThread.start();
        updatingReferenceThread.start();
    }

}

これは、スレッドセーフをテストするために使用しているプログラムです。

変な挙動

私のプログラムがいくつかの反復の間に開始されると、出力フラグの値を取得します。 != のチェックは同じ参照で失敗します。しかし、いくつかの反復の後、出力は一定の値になります。 false になり、さらに長時間プログラムを実行しても、一度も true の出力が得られない。

出力が示すように、いくつかのn(固定ではない)反復の後、出力は一定の値であり、変化しないようです。

出力です。

いくつかのイテレーションに対して

1494:true
1495:true
1496:true
19970:true
19972:true
19974:true
//after this there is not a single instance when the condition becomes true

どのように解決するのですか?

同期がない場合、このコード

Object a;

public boolean test() {
    return a != a;
}

true . のバイトコードです。 test()

    ALOAD 0
    GETFIELD test/Test1.a : Ljava/lang/Object;
    ALOAD 0
    GETFIELD test/Test1.a : Ljava/lang/Object;
    IF_ACMPEQ L1
...

を読み込んでいるのがわかるように、フィールド a をローカル変数に二度ロードします。これは非アトミックな操作で、もし a が別のスレッドで変更された場合、比較の結果 false .

また、メモリの可視性の問題がありますが、これは a への変更が、現在のスレッドから見えるという保証はありません。