2

Collections.synchronizedCollection(map)反復中にコードを同期する必要がある場合、マップを でラップするポイントは何ですか?

  Collection<Type> c = Collections.synchronizedCollection(myCollection);
 synchronized(c) {
        for (Type e : c)
            foo(e); }

ラップした後、スレッドセーフにするべきではありませんか?

4

3 に答える 3

3

反復中にコードを同期する必要がある場合、マップを Collections.synchronizedCollection(map) でラップするポイントは何ですか?

個々の操作をスレッドセーフにするため。(個人的には一般的には悪い考えだと思いますが、それは別の問題です。無意味ではなく、有用性が限られているだけです。)

ラップした後、スレッドセーフにするべきではありませんか?

個々の操作については、はい。ただし、反復には多くのステップが含まれます。これらの個々のステップはそれぞれ同期されますが、コレクションはステップで変更され、反復子が無効になる可能性があります。ループが次のように展開されることを忘れないでください。

for (Iterator<Type> iterator = c.iterator(); iterator.hasNext(); ) {
    Type e = iterator.next();
    ...
}

反復をスレッドセーフにする必要があるjava.util.concurrent場合は、反復中にコレクションが変更された場合に何が保証​​され、何が保証されないかについての警告に注意しながら、... のコレクションの 1 つを使用する必要があります。

于 2013-07-06T12:12:49.863 に答える
0

@jonskeet の @jule の回答に追加して、繰り返しのロックを必要としないConcurrentHashMap( http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html ) の使用を検討する必要があります。

于 2013-07-06T12:17:01.627 に答える
0

ラップした後、個々のメソッドはスレッド セーフになりますが、反復ではメソッドを繰り返し呼び出す必要があり (返された Iterator で iterator、次に next および hasNext)、これらのメソッド間の同期はありません。これが、反復を同期する必要がある理由です。

また、(単に反復コードを同期するのではなく) 同期コレクションを使用する必要があります。そうしないと、アイテムを追加または削除するメソッドが同期されず、同期ブロックを使用した場合でも反復中に変更が加えられる可能性があるためです。

于 2013-07-06T12:13:47.613 に答える