5

Collection フレームワークで、外部同期が内部同期 (Vector、HashTable など) よりも速いのはなぜですか? どちらも同じメカニズムを使用しているのに?

内部同期と外部同期の正確な意味と、それらの違いは何ですか?

誰かが例を挙げて説明できると本当に助かります。

4

2 に答える 2

10

内部同期と外部同期の正確な意味と、それらの違いは何ですか?

外部同期とは、呼び出し元 (ユーザー) がsynchronizedキーワードまたは他のロックを使用して、別のクラスが複数のスレッドによってアクセスされないように保護する場合です。通常、問題のクラス自体が同期されていないSimpleDateFormat場合に使用されます。これが代表的な例です。また、スレッド間のシグナル伝達が必要な場合にも使用できます。同時コレクションを処理する場合でも使用できます。

外部同期が内部同期(Vector、HashTableなど)よりも速いのはなぜですか? どちらも同じメカニズムを使用しているのに?

外部同期は必ずしも高速ではありません。通常、クラスは、呼び出し元がすべてのメソッド呼び出しをsynchronizedブロックにラップするのではなく、コードのクリティカル セクションを同期する必要がある時期を正確に判断できます。

andを使用せ、代わりにorメソッドを使用するという一般的な推奨事項について話している場合、これはandが古い/古いクラスと見なされるためです。ラップされたorは、より良い解決策と見なされます。VectorHashTableCollections.synchronizedList(...)synchronizedMap(...)VectorHashTableArrayListHashMap

@Chris が指摘したように、クラスに多数の変更を次々に加える必要がある場合、外部同期の方が高速になることがあります。外部で一度ロックしてからクラスに複数の変更を実行することで、各変更を内部でロックするよりもうまく機能します。複数のロック呼び出しが連続して行われるよりも、単一のロックの方が高速です。

誰かが例を挙げて説明できると本当に助かります。

の代わりにVector、人々は通常、ラップArrayListされた方がパフォーマンスが優れていると推奨します。これにより、同期されていないArrayListクラスが、外部で同期されるラッパー クラスにラップされます。

List<Foo> list = Collections.synchronizedList(new ArrayList<Foo>());

内部と外部の一般的な観点から、複数のスレッドが同時に使用できるようにする次のクラスを検討してください。

public class Foo {
    private int count;
    public void addToCount() {
        count++;
        log.info("count increased to " + count);
    }
}

外部同期を使用して、すべての呼び出しをブロックにラップできaddToCount()ますsynchronized

synchronized (foo) {
   foo.addToCount();
}

または、クラス自体が内部同期を使用して、ロックを行うことができます。これは、ロガー クラスがロックの一部である必要がないため、パフォーマンスが向上します。

public void addToCount() {
    int val;
    synchronized (this) {
       val = ++count;
    }
    // this log call should not be synchronized since it does IO
    log.info("count increased to " + val);
}

もちろん、この場合、Fooクラスは本当に an を使用し、AtomicInteger内部で独自の再入を処理する必要があります。

private final AtomicInteger count = new AtomicInteger(0);
public void addToCount() {
    int val = count.incrementAndGet()
    log.info("count increased to " + val);
}
于 2013-09-27T16:15:07.117 に答える