2013-08-28 6 views
15

私は、並行ハッシュマップで約1000個の要素を扱っています。デフォルトの同時実行レベルは16です。誰も私のシナリオに適した並行性レベルや並行性レベルが複数のスレッドの処理にどのような影響を及ぼすかを特定できるアルゴリズムや要因を教えてください。 ConcurrentHashMapの並行性レベルを適切に使用して設定する方法は?

ConcurrentHashMap<String, String> map=new ConcurrentHashMap<String, String>(500,1,20);    
を効率的

+0

マップに同時にアクセスできるスレッドの数は分かりますか? – rolve

+0

これは、現在システムにログインしているユーザーがいないことに依存します。 – csk

答えて

15

ドキュメントによれば、私の同時実行レベル(ダミー値).Needこれを設定することである:更新操作のうち

せ並行処理が 任意concurrencyLevelコンストラクタによって案内されます引数 (デフォルトは16)、これは内部サイジングのヒントとして使用されます。 テーブルは内部的にパーティション化されており、指定された の同時更新を競合なしに許可しようとします。ハッシュテーブル内の配置 は本質的にランダムなので、実際の並行処理は になります。 スレッドを同時に変更するように値を選択するのが理想的です。 を使用すると、必要な値よりも大幅に高い値を指定すると、スペースと時間を無駄にする可能性があります. と大幅に低い値を指定すると、スレッドの競合が発生する可能性があります。

は、だから、1つの質問に答える必要があります。

これまで並行して表を変更するスレッドの数は何ですか?

+0

スレッドの数が100ではないと考えることができます – csk

+1

答えが100の場合、同時実行レベルを100に設定できます。 – Tala

+0

@Talaシステムに100のスレッドがあるとします。 90個のスレッドがこのマップを走査し、最大10個のスレッドが一度にこのマップを変更(put/remove)しようとすると、同時実行レベルは何ですか?答えてください。 –

1

16マップが分割される領域のデフォルト数です。 ConcurrentHashMap(リーダースレッドの場合)は、ロックされずに(ほとんどの場合)実行されます。 ライタースレッドの数は、心配する必要があるものです。そしてこの数はあなたが持っている地域の数と同じでなければなりません。

2

ConcurrentHashMapを使用すると、複数のリーダーが同時にブロックすることなく読み取ることができます。これは、マップを並行性レベルに基づいて異なる部分に分割し、更新中にMapの一部のみをロックすることによって実現されます。デフォルトの同時実行レベルは16です。したがって、マップは16の部分に分割され、各部分は異なるロックで管理されます。これは、マップの異なる部分で動作するまで、16スレッドがマップ上で同時に動作できることを意味します。これにより、スレッドセーフティを損なわずにConcurrentHashMapを高性能にすることができます。

3

のJava 8:

ConcurrentHashMapではなく、各バケットは、固有の同期を使用して「ストライプ」として機能し、全く固定ロックストライピング方式を使用していません。

コードソースから:

/** Implementation for put and putIfAbsent */ 
final V putVal(K key, V value, boolean onlyIfAbsent) { 
    ... 
    Node<K,V> f; int n, i, fh; 
    ... 
    else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { 
    ... 
     synchronized (f) { 
      ... 
     } 
} 

そしてコンストラクタはドキュメントが言うようにジャストサイズのヒントとしてそれを使用するパラメータを持っています。

concurrencyLevel - 同時に更新されるスレッドの推定数。実装では、この値をサイジングヒントとして使用できます。

ソース:

public ConcurrentHashMap(int initialCapacity, 
         float loadFactor, int concurrencyLevel) { 
    if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0) 
     throw new IllegalArgumentException(); 
    if (initialCapacity < concurrencyLevel) // Use at least as many bins 
     initialCapacity = concurrencyLevel; // as estimated threads 
    long size = (long)(1.0 + (long)initialCapacity/loadFactor); 
    int cap = (size >= (long)MAXIMUM_CAPACITY) ? 
     MAXIMUM_CAPACITY : tableSizeFor((int)size); 
    this.sizeCtl = cap; 
} 

だからConcurrentHashMapはあなたのためにそれを処理します、自分でそれを考慮する必要はありません。

+0

コメントからjava 8 ConcurrentHashMap実装: – popalka

+0

別のロックオブジェクトを各ビンに関連付けるために必要なスペースを無駄にしたくないので、代わりにビンリスト自体の最初のノードをロックとして使用します。これらのロックに対するロックのサポートは、組み込みの「同期」モニターに依存します。 – popalka

関連する問題