2016-05-29 9 views
-2

同時ハッシュマップでは、複数のスレッドがセグメントロックを使用して同時に読み書きを行うことができます。 私の質問は: スレッドt1がバケットに書き込み中で、スレッドt2が同じバケット上で読み込み中で、その逆の場合にJavaが内部的にマップを管理する方法は? Javaはマップ上に書き込みを開始し、書き込み操作後にマージするか、あるいはJavaが実際に採用している方法は何ですか?同時ハッシュマップJavaの内部メカニズム

正解を待っています。

+0

いくつかの基本的なグーグルが順番にあります:http://javahungry.blogspot.com/2015/02/how-concurrenthashmap-works-in-java-internal-implementation.html – csvan

+1

さらに、このような質問は、ソースコードを読む。 – Nikem

+0

私はそれを行ったことがあり、それは単に何が可能で何がないかを言及しています。それはjavaがそれをどのように扱うかを説明していませんでした。答えが分かれば答えてください。なぜあなたは不適切とマークしたのですか?あなたがアスンワーを知らないなら、それを飛ばすことができます。 –

答えて

1

いいえ、Javaはマップまたはセグメントのコピーを作成せず、書き込み操作後にコピーをマップに「マージ」しません。
putおよびgetメソッドは、セグメントにロックを設定するので、2つのスレッドは同時に同じセグメントにアクセスできません。

putgetの実装を見てみてください。
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/ConcurrentHashMap.java#ConcurrentHashMap.put%28java.lang.Object%2Cjava.lang.Object%29

907  public V put(K key, V value) { 
908   if (value == null) 
909    throw new NullPointerException(); 
910   int hash = hash(key.hashCode()); 
911   return segmentFor(hash).put(key, hash, value, false); 
912  } 

795  public V get(Object key) { 
796   int hash = hash(key.hashCode()); 
797   return segmentFor(hash).get(key, hash); 
798  } 

どちらの方法は、キーのハッシュを計算し、その後、与えられたハッシュのためのセグメントを返すことsegmentFor(hash)を呼び出し、その後、putを呼び出しますこのセグメントのメソッドはgetです。


セグメントの宣言はここで、それはReentrantLockのの子孫は次のとおり
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/ConcurrentHashMap.java#ConcurrentHashMap.Segment

static final class Segment<K,V> extends ReentrantLock implements Serializable { 

及びセグメント内get ANG putの実装:

351   V readValueUnderLock(HashEntry<K,V> e) { 
352    lock(); 
353    try { 
354     return e.value; 
355    } finally { 
356     unlock(); 
357    } 
358   } 
359 
360   /* Specialized implementations of map methods */ 
361 
362   V get(Object key, int hash) { 
363    if (count != 0) { // read-volatile 
364     HashEntry<K,V> e = getFirst(hash); 
365     while (e != null) { 
366      if (e.hash == hash && key.equals(e.key)) { 
367       V v = e.value; 
368       if (v != null) 
369        return v; 
370       return readValueUnderLock(e); // recheck 
371      } 
372      e = e.next; 
373     } 
374    } 
375    return null; 
376   } 

444   V put(K key, int hash, V value, boolean onlyIfAbsent) { 
445    lock(); 
446    try { 
447     int c = count; 
448     if (c++ > threshold) // ensure capacity 
449      rehash(); 
450     HashEntry<K,V>[] tab = table; 
451     int index = hash & (tab.length - 1); 
452     HashEntry<K,V> first = tab[index]; 
453     HashEntry<K,V> e = first; 
454     while (e != null && (e.hash != hash || !key.equals(e.key))) 
455      e = e.next; 
456 
457     V oldValue; 
458     if (e != null) { 
459      oldValue = e.value; 
460      if (!onlyIfAbsent) 
461       e.value = value; 
462     } 
463     else { 
464      oldValue = null; 
465      ++modCount; 
466      tab[index] = new HashEntry<K,V>(key, hash, first, value); 
467      count = c; // write-volatile 
468     } 
469     return oldValue; 
470    } finally { 
471     unlock(); 
472    } 
473   } 

これらのメソッドは、単にジョブを実行している間にセグメントにアクセスする/アクセスできないようにする/許可するためにlock()とを呼び出します。

関連する問題