9

同期されたメソッドがあり、そのメソッド内で、次のようにハッシュマップを更新するとします。

public synchronized void method1()
{
    myHashMap.clear();
    //populate the hashmap, takes about 5 seconds.
}

これで、method1が実行され、ハッシュマップが再入力されているときに、ハッシュマップの値を取得しようとしている他のスレッドがある場合、それらはブロックされると思いますか?

同期メソッドを使用する代わりに、ハッシュマップを以下のようにConcurrentHashMapに変更した場合、どのように動作しますか?

public void method1()
{
     myConcurrentHashMap.clear();
    //populate the hashmap, takes about 5 seconds.
}

Collections.synchronizedMapを使用するとどうなりますか?同じですか?

4

3 に答える 3

14

CHM(ConcurrentHashMap)は、共通ロックのすべてのメソッドを同期して、一度に1つのスレッドへのアクセスを制限する代わりに、ロックストライピングと呼ばれるよりきめ細かいロックメカニズムを使用して、より高度な共有アクセスを可能にします。任意に多くの読み取りスレッドがマップに同時にアクセスでき、リーダーはライターと同時にマップにアクセスでき、限られた数のライターが同時にマップを変更できます。その結果、同時アクセスでのスループットがはるかに高くなり、シングルスレッドアクセスのパフォーマンスが低下することはほとんどありません。ConcurrentHashMapは、他の同時コレクションとともに、ConcurrentModificationExceptionをスローしないイテレーターを提供することにより、同期されたコレクションクラスをさらに改善し、反復中にコレクションをロックする必要をなくします。

すべての改善と同様に、まだいくつかのトレードオフがあります。サイズやisEmptyなど、マップ全体を操作するメソッドのセマンティクスは、コレクションの同時性を反映するためにわずかに弱められています。サイズの結果は、計算されるまでに古くなる可能性があるため、実際には単なる見積もりであり、サイズは正確なカウントではなく概算を返すことができます。最初はこれは気がかりなように思えるかもしれませんが、実際には、sizeやisEmptyなどのメソッドは、これらの量がターゲットを移動しているため、並行環境でははるかに有用ではありません。



第二に、Collections.synchronizedMap

これは、同期されたメソッドを備えた単純なHashMapです-私はそれをCHMの非推奨のduteと呼んでいます

于 2012-09-27T19:26:31.553 に答える
8

HashMap同期されたすべての読み取りおよび書き込みアクションが必要な場合は、 ;synchronizeにアクセスするすべてのメソッドにonを設定する必要があります。HashMap1つのメソッドだけをブロックするだけでは不十分です。

ConcurrentHashMapロックせずにデータへのスレッドセーフアクセスを許可します。つまり、あるスレッドで値を追加/削除すると同時に、例外が発生することなく別のスレッドで値を取得できます。ConcurrentHashMapのドキュメントも参照してください

于 2012-09-27T19:30:57.567 に答える
0

あなたはおそらくすることができます

volatile private HashMap map = newMap();

private HashMap newMap() {
    HashMap map = new HashMap();
    //populate the hashmap, takes about 5 seconds
    return map;
}

public void updateMap() {
    map = newMap();
}

リーダーは一定のマップを見るので、読み取りは同期を必要とせず、ブロックされません。

于 2012-09-27T19:32:54.947 に答える