2013-09-27 32 views
5

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

内部同期と外部同期の正確な意味と、それらがお互いにどのように違うのですか?

誰かが例を説明することができれば、本当に役に立ちます。

+2

マイナーサイド以外:スレッドセーフなコードを書くには、同期コレクションを使用するよりもはるかに優れた方法があります(通常、内部同期です。 (ブロックする必要がない場合に最小限のオーバーヘッドが発生するロックフリーの同時データ構造など) – millimoose

答えて

9

内部と外部の同期の意味はどういう意味があり、どのようにお互いに違いがありますか?

外部同期は、呼び出し元(あなた)が​​キーワードまたは他のロックを使用して、複数のスレッドがアクセスする別のクラスを保護する場合です。問題のクラスがではなく、自体が同期化されていない場合は、通常使用されます。SimpleDateFormatが最も良い例です。また、スレッド間でシグナリングを必要とする場合(同時収集を扱う場合)にも使用できます。

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

外部同期は、ではなく、が必然的に高速です。通常、クラスは、呼び出し側が​​ブロック内のすべてのメソッド呼び出しをラップする代わりに、コードの重要な部分を同期させる必要があるときを正確に判断できます。

あなたがない使用VectorHashTableに一般的な推奨事項について話して、代わりにCollections.synchronizedList(...)またはsynchronizedMap(...)メソッドを使用している場合VectorHashTableが古い/古いの最新クラスとして見られているので、これはです。ラップされたArrayListまたはHashMapは、より良い解決策と見なされます。

@Chrisが指摘しているように、クラスのいくつかの変更を次々と行う必要があるときに、外部同期が速くなることがあります。外部で一度ロックしてからクラスを複数回変更すると、内部的にロックされている各変更よりも効果的です。複数のロック呼び出しよりも速い単一のロックが連続して行われます。

例を説明することができれば、本当に役に立ちます。

Vectorの代わりに、一般的には、より良いパフォーマンスを得るために、ArrayListをラップすることをおすすめします。これは、非同期のArrayListクラスを外部同期するラッパークラスにラップします。

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

あなたは外部同期を使用することができますし、addToCount()にすべてのコールをラップ:一般的には、外部対内部の点で

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

は、あなたが複数のスレッドが同時にそれを使用できるようにしたい、次のクラスを考えます

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

またはクラス自体の内部同期を使用し、ヨーヨーのためのロックを行うことができます。​​ブロックでu。もちろん

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クラスは本当にこのケースでAtomicIntegerを使用する必要があり、内部で独自の再入の世話をする:これはロガークラスはロックの一部である必要はありませんので、パフォーマンスが向上し

private final AtomicInteger count = new AtomicInteger(0); 
public void addToCount() { 
    int val = count.incrementAndGet() 
    log.info("count increased to " + val); 
} 
+0

よい例を紹介していただきありがとうございます...... – Rajeev

7

銀行で働いているとします。セーフを使用する必要があるたびに、ロックを解除してから、ロックを解除してからロックし直す必要があります。

ここで、金庫に50個のボックスを運ぶ必要があるとしましょう。

  1. は、個別の上に開口部を各ボックスを運び、(非常に重い)ドアを閉めするたびに
  2. 銀行にフロントドアをロックし、金庫を開いたまま、せずに50回の旅行をする:あなたは2つのオプションがあります内部の金庫扉に触れる

どちらが速いのですか?

+0

良い類推ですが、銀行外出する必要がある場合は外部が悪いです毎回。あなたは都市や国をロックすることはできません – Mordan

+0

@モルダン私はあなたが少しあまりにも比喩を伸ばしていると思います。コンピュータ上の抽象化は、地方自治体によって厳密に妨げられるわけではない。 Java JVMはこれの良い例です。ガベージコレクションを実行すると、実装が完了するまで文字通りすべてが実行されないようにする「世界を止める」ロックを実行する実装があります。私はあなたがこれのために努力すべきだと言っているわけではありませんが、それは聞いたことがありません。 –

関連する問題