2

次のコードがスレッドセーフかどうか知りたいです:

public static void methodA () {
    // given that mutableObject is not thread-safe (no lock/synchronization used)
    MutableObject mo = new MutableObject();
    mo.setSomeValue(100);  // set an int value

    // the mutableList variable must be final in order to pass it to the thread block
    final List<mutableObject> mutableList = new ArrayList<mutableObject>();  
    mutableList.add(mo);
    Thread t = new Thread() {
                      @Override 
                      public void run() {
                          for (mutableObject e : mutableList) {
                              e.printIntValue();  // print 100 or 0?
                          }
                      }
                }
    t.start();
}

それで、ここに質問があります。明示的な同期/ロックが使用されていなくても、「mutableList」参照から到達可能な*すべてのコンテンツが新しいスレッドに表示されるかどうかはわかりません。(可視性の問題) つまり、新しいスレッドは 0 または 100 を出力しますか? 0 は int データ型のデフォルトのプリミティブ値であるため、メイン スレッドによって設定された値 100 が表示されない場合は 0 を出力します。

すなわち。「到達可能なコンテンツ」とは、次のことを意味します。

  1. MutableObject が保持する int 値 100
  2. ArrayList が保持する MutableObject への参照

回答ありがとうございます。

4

2 に答える 2

2

このコードはスレッドセーフです。他のスレッドが同じオブジェクトにアクセスする方法がないためです。これらのオブジェクトはスレッドの内部methodA()およびメソッド内で使用できるためrun()です。どちらもデータを変更しません。

少なくとも 2 つのスレッドが同じデータを操作すると、スレッド セーフの問題が発生します。これはあなたの場合ではありません。

コードをスレッドセーフにしないようにする方法は? いくつかの方法があります。

  1. mo.setSomeValue(100);を呼び出した後に行を追加しt.start()ます。これは、スレッドを起動した後、同じオブジェクトを操作する 2 つのスレッド (メイン スレッドと他のスレッド) があることを意味しますmo。ただし、これにより例外が発生することはありません。

  2. 行を追加しますmutableList.remove(0)。これConcurrentModificationException、スレッドが十分に速く開始され、メインスレッドが到着して命令を削除する前にループに入ることができた場合に発生する可能性があります。

于 2013-05-14T13:04:52.490 に答える
0

ここではスレッドセーフの問題はありません。オブジェクトmoとオブジェクトmutableListは、関数呼び出し内で定義およびインスタンス化されます。関数が呼び出されるたびに、2 つの新しいオブジェクト (上記) が作成されます。スレッドセーフでない値は一切ありません。

于 2013-05-14T13:08:57.577 に答える