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 .

4

2 に答える 2

12

コレクションの実装でできることのほとんどは、個々のメソッド呼び出しが同期synchronizedされることを保証することです。ただし、反復には必ず複数の個別のメソッド呼び出しが含まれるため、同期コレクションのユーザーは、反復全体を自分で同期する必要があります。

たとえば、 で同期しなかった場合c、コレクションの内容が と の間i.hasNext()で変化する可能性があります。i.next()要素がある状態からそれ以上の要素を持たない状態になることさえあり、その場合i.next()は失敗します。

于 2013-04-03T20:59:03.260 に答える
7

クラスのすべてのメソッドを個別に同期しても、それらのメソッドの集約 ( group で呼び出し) はスレッドセーフになりません。を同期ブロックでラップすることによりIterator、反復子の特定のインスタンスが、複数のスレッドによる他の呼び出しに散在して呼び出される個々のメソッドを持つことから保護されます。

一度呼び出す.add()と安全であり、論理ステートメントを完了するために複数回呼び出す必要がある場合、他のすべての呼び出しをブロックしない限り、呼び出し.add()の間に他の誰かが何かを追加したり削除したりしていないという保証はありません(またはコレクションを表す変数を使用します。.add().add()synchronizing

Iterator、コレクションの個々のメソッドに対して複数の呼び出しを行います。synchronized単一transactionの並べ替えとして実行するには、それらをすべて単一のブロックにラップする必要があります。あなたの実装のソースコードを調べると、 Iterator私が何を意味するかがわかります。これは、基になる実装に対して複数の個別の呼び出しを行うためのソース コードですList。そのため、それらはすべて、決定論的であるために同じスレッドによって中断されずに実行される必要があります。

  @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();
        }
    };
    }

ソースAbstractList.iterator()は、複数の呼び出しを行うさらに複雑なロジックを示しています。

より良いラッパーは、それらをImmutableコレクションにラップすることです。そうすれば、呼び出し間で基になるコレクションを変更できないことを保証できます。

于 2013-04-03T21:00:36.373 に答える