同時ハッシュマップでは、複数のスレッドがセグメントロックを使用して同時に読み書きを行うことができます。 私の質問は: スレッドt1がバケットに書き込み中で、スレッドt2が同じバケット上で読み込み中で、その逆の場合にJavaが内部的にマップを管理する方法は? Javaはマップ上に書き込みを開始し、書き込み操作後にマージするか、あるいはJavaが実際に採用している方法は何ですか?同時ハッシュマップJavaの内部メカニズム
正解を待っています。
同時ハッシュマップでは、複数のスレッドがセグメントロックを使用して同時に読み書きを行うことができます。 私の質問は: スレッドt1がバケットに書き込み中で、スレッドt2が同じバケット上で読み込み中で、その逆の場合にJavaが内部的にマップを管理する方法は? Javaはマップ上に書き込みを開始し、書き込み操作後にマージするか、あるいはJavaが実際に採用している方法は何ですか?同時ハッシュマップJavaの内部メカニズム
正解を待っています。
いいえ、Javaはマップまたはセグメントのコピーを作成せず、書き込み操作後にコピーをマップに「マージ」しません。
put
およびget
メソッドは、セグメントにロックを設定するので、2つのスレッドは同時に同じセグメントにアクセスできません。
put
とget
の実装を見てみてください。
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()
とを呼び出します。
いくつかの基本的なグーグルが順番にあります:http://javahungry.blogspot.com/2015/02/how-concurrenthashmap-works-in-java-internal-implementation.html – csvan
さらに、このような質問は、ソースコードを読む。 – Nikem
私はそれを行ったことがあり、それは単に何が可能で何がないかを言及しています。それはjavaがそれをどのように扱うかを説明していませんでした。答えが分かれば答えてください。なぜあなたは不適切とマークしたのですか?あなたがアスンワーを知らないなら、それを飛ばすことができます。 –