1

Memory Consistancy Propertyから、次のことがわかります。

これは、あるスレッドでオブジェクトを作成して ConcurrentLinkedQueue に入れると、別のスレッドがオブジェクトのすべてのプロパティを参照し、そのオブジェクトで他の同期が行われないことを意味しますか?

例えば:

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public String getName(){

     return name;

  }

  public int getIndex(){

     return index;

  }

}

public class SharedQueue{

   public static ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

}

1つのスレッドで:

…………

Complex complex = new Complex(12, "Sam");

SharedQueue.queue.add(complex);

…………

別のスレッドで

......

Complex complex = SharedQueue.queue.poll();

System.out.printly(complex.getIndex() + ";" + complex.getName());

…………

2 番目のスレッドは確実にcomplexオブジェクトのプロパティを認識しますか? 最初のスレッドがオブジェクトをキューに置いた後、2 番目のスレッドがたまたまオブジェクトをフェッチして出力した場合。

通常、オブジェクトが共有されている場合は、マルチスレッド環境でオブジェクトを同期する必要があることがわかっています。

お気に入り

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public synchronized String getName(){

     return name;

  }

  public synchronized int getIndex(){

     return index;

  }

}
4

4 に答える 4

1
  1. すべてのスレッドは、参照を取得できるすべてのオブジェクトを参照するため、これはコレクションにも当てはまります。並行コレクションは、2 つ以上のスレッドが同時にアクセスしても中断しないように同期を使用しているため (たとえば、for ループが中断する可能性があります)、スレッド間でオブジェクトを共有するためにそれらを使用できます。

  2. 上記の Complex クラスのようにオブジェクトが不変、つまり読み取り専用である場合 (final 修飾子を追加)、スレッドセーフであるため、オブジェクトへのアクセスを同期する必要はありません。

同期のポイントは、変数が n 回の操作で一貫していることを確認することです。例:

計算したい場合

i = i + 2;

次に、これは、最初に i の値を読み取り、2 を加算してから、値を i に戻すことで構成されます。

2 を追加した直後に他のスレッドが来て i を更新すると、前の値 + 2 に基づいて合計を保持し、i に戻すため、この更新を上書きすることになります。

于 2011-03-23T15:30:33.337 に答える
0

その通り。この場合ConcurrentLinkedQueue、シンクロナイザーとして機能します。

于 2011-03-23T15:22:57.697 に答える
0

つまり、スレッドAがオブジェクトをコレクションに配置し、スレッドBがそこからオブジェクトを取得した場合、スレッドBは、オブジェクトをコレクションに配置する前にスレッドAによって実行されたアクションの結果(および、オブジェクトがコレクションに配置される前に発生したアクション)を確認できます。他のスレッドなど)。これらのアクションには、オブジェクトの初期化(スレッドAによって実行された場合)が含まれるため、スレッドBはオブジェクトを一貫した状態で見ることができます。

オブジェクトをコレクションに配置した後にスレッドAで発生したアクション、または他のスレッドのアクション(上記のように、推移的な発生-順序の前に関連するアクションを除く)については保証されないため、同期が必要であることに注意してください。コレクションに配置した後でオブジェクトを変更する場合。

ちなみに、コンストラクターのアクションは同期されていないため、「通常の場合」のサンプルは破損しています。

于 2011-03-23T15:23:23.737 に答える
0

JSR 133は、コンストラクターが完了すると、オブジェクトの最終フィールドが完全であり、すべてのスレッドに表示されることも指定します。このサポートは、Java 5.0 (2004 年) で追加されました。すべてのスレッドでオブジェクトが正しく表示されるようにするために必要なその他のアクションはありません。

この場合、不変オブジェクトで synchronized を使用しても何も達成されません。

そうではないと述べているドキュメントはたくさんあり、これらは一般に 2004 年よりも前のものです。;)

于 2011-03-23T15:08:30.070 に答える