2013-04-03 6 views
7

cはすでに同期化されたコレクションなのでスレッドセーフです。しかし、繰り返しのためにもう一度synchronized(c)を使用する必要がありますか?本当に混乱しています。ありがとう。同期化されたコレクション

は、「繰り返し処理を行う場合、ユーザーが手動で返さ コレクションで同期をとる必要があります。このアドバイスに従うこと

Collection c = Collections.synchronizedCollection(myCollection); 
... 
synchronized(c) { 
    Iterator i = c.iterator(); // Must be in the synchronized block 
    while (i.hasNext()) { 
     foo(i.next()); 
    } 
} 

障害が非決定論的動作になることがあります。」 http://docs.oracle.com/javase/6/docs/api/java/util/Collections

答えて

10

ほとんどの​​コレクションの実装では、個々のメソッド呼び出しが同期されていることを保証することができます。しかし、反復には複数の別個のメソッド呼び出しが必然的に必要なので、同期されたコレクションのユーザーは、自分自身で繰り返し全体を同期させる必要があります。例えば

あなたはcで同期していない場合は、コレクションの内容はi.hasNext()i.next()の間で変更することができます - それもi.next()が失敗した場合にはそれ以上の要素を持っていないに要素を持つから行くことができます。

+0

「必ずしも複数の別個のメソッド呼び出しを必要とする」とはどういう意味ですか? – user697911

+1

@ user697911: 'i.hasNext()'と 'i.next()'は別々の2つのメソッド呼び出しであり、 'Collections.synchronizedCollection'の実装では、' i.hasNext () 'と' i.next() 'のようになります。 –

+0

したがって、concurrentHashmapは同じですか?また、反復で同時にハッシュ関数を同期させる必要がありますか? – user697911

4

クラスのすべてのメソッドを個別に同期させても、それらのメソッドのスレッドセーフである集約(グループ内での呼び出し)は行われません。 Iteratorを同期ブロックにラップすると、イテレータの特定のインスタンスが、複数のスレッドによる他の呼び出しと散在した個別のメソッドを持つのを防ぎます。

それが安全になると私は.add()を呼び出す場合、私は論理的な文を完了するために、.add()を複数回呼び出す必要があれば、他の誰かが私でない限り、私の.add()呼び出しの間に何かを何か他のものを追加または削除していないという保証はありません他のすべてをブロックし、.add()(または他の方法)をsynchronizingで、コレクションを表す変数に呼び出します。

Iteratorは、コレクション上の個々のメソッドを複数回呼び出すため、すべて​​ブロックにラップして、1つのtransactionのソートとして実行する必要があります。 Iteratorの実装のソースコードを調べると、私の言いたいことが分かります。 Listのソースコードは、基になる実装への複数の個別の呼び出しを行うため、同じスレッドによって途切れない順序で実行され、確定的に実行される必要があります。 AbstractList.iterator()ため

@Override 
    public Iterator<A> iterator() { 
     if (tail == null) 
      return emptyIterator(); 
    return new Iterator<A>() { 
     List<A> elems = List.this; 
     public boolean hasNext() { 
     return elems.tail != null; 
     } 
     public A next() { 
       if (elems.tail == null) 
        throw new NoSuchElementException(); 
     A result = elems.head; 
     elems = elems.tail; 
     return result; 
     } 
     public void remove() { 
     throw new UnsupportedOperationException(); 
     } 
    }; 
    } 

source複数の呼び出しを行い、さらに複雑なロジックを示しています。

より包括的なラッパーがコレクションの中にラップしている場合は、コール間で基礎となるコレクションを変更できないことを保証します。

+1

最高の説明私は出会った! – kellogs

関連する問題