簡體   English   中英

java.util.Hashtable實現代碼局部變量到元素表重新分配

[英]java.util.Hashtable implementation code local variable to elements table reassignment

我想知道為什么java.util.Hashtable方法通過本地分配的變量對元素數組執行操作,而不是直接訪問類成員。 是否與同步有關(在方法調用之間保持元素數組的一致狀態?)

例如: Entry<?,?> tab[] = table;

 private void addEntry(int hash, K key, V value, int index) {
420         modCount++;
421 
422         Entry<?,?> tab[] = table;
423         if (count >= threshold) {
424             // Rehash the table if the threshold is exceeded
425             rehash();
426 
427             tab = table;
428             hash = key.hashCode();
429             index = (hash & 0x7FFFFFFF) % tab.length;
430         } 

或者在

456     public synchronized V put(K key, V value) {
457         // Make sure the value is not null
458         if (value == null) {
459             throw new NullPointerException();
460         }
461 
462         // Makes sure the key is not already in the hashtable.
463         Entry<?,?> tab[] = table;
464         int hash = key.hashCode();
465         int index = (hash & 0x7FFFFFFF) % tab.length;
466         @SuppressWarnings("unchecked")
467         Entry<K,V> entry = (Entry<K,V>)tab[index];
468         for(; entry != null ; entry = entry.next) {
469             if ((entry.hash == hash) && entry.key.equals(key)) {
470                 V old = entry.value;
471                 entry.value = value;
472                 return old;
473             }
474         }
475 
476         addEntry(hash, key, value, index);
477         return null;
478     }

我感覺不好,只留下評論,這個問題值得一個合適的回答,所以這里有一個快速的嘗試重提 (公頃)的意見。

  • Hashtable是同步的(所有公共方法都是synchronized ,或者返回一個同步的集合( keySet()entrySet()values() )),這使得它的線程安全 (某些規則和限制可能適用)
  • rehash()方法protected :可以從子類調用它。
  • 但它不是synchronized ,因此子類的實例可以同時調用rehash()到另一個需要訪問table
    因此,為了避免table上的競爭條件,這些方法保存對數組的引用的本地副本,然后可以安全地使用該本地數組:如果調用rehash() ,它將構建一個新數組而不會干擾其他工作在舊的線程。

JDK 1.0.2的版本已經是這樣了(在這里找到它,Windows .exe是可自行提取的zip文件,因此unzip處理,在那里你會找到src.zip - 有趣的是看到Hashtable.java內部有3個類,沒有內部類,如1.1)中所介紹的那樣。

這種設計鼓勵繼承Hashtable以從其功能中受益,但組合應該受到青睞。 我發現了一個特定於Hashtable子類的bug條目 (盡管不是關於線程安全性),其中Josh Bloch說:

使用委托而不是子類可以避免這種問題。

在評論中引用@pvg,獲得一個很好的總結:

一個更廣泛的答案是,這基本上是一個90年代早期的設計,它的壽命很長,而且它顯示出來。 它是一個通過子類同時嘗試同時具有線程安全性和可擴展性的類,這是類庫在以后的設計迭代中避免的。

這很簡單 - rehash()將重寫table字段,因此將它們保存到臨時變量以便以后訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM