java.util.Hashtable实现代码局部变量到元素表重新分配

时间:2017-08-13 21:31:26

标签: java collections

我想知道为什么var tracker: any[] = []; 方法通过本地分配的变量对元素数组执行操作,而不是直接访问类成员。它是否与同步有关(在方法调用之间保持元素数组一致?)

例如: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         } 

2 个答案:

答案 0 :(得分:2)

我感觉很糟糕,只留下评论,这个问题值得一个正确的答案,所以这里是一个快速尝试重新发布(ha)这些评论。

  • Hashtable已同步(所有公开方法均为synchronized,或返回同步集合(keySet()entrySet()values())) thread safe (某些规则和限制可能适用)
  • rehash()方法是protected:可以从子类调用它。
  • 但它不是synchronized,因此子类的实例可以同时调用rehash()另一个需要访问table的方法。 因此,为了避免table上的竞争条件,这些方法会保存对数组的引用的本地副本,然后可以安全地使用该本地数组:如果调用rehash(),它将构建一个新数组不会干扰处理旧数组的其他线程。

来自JDK 1.0.2的版本就像那样(找到它here,Windows .exe是自我提取的zip文件,所以unzip处理那个,在那里你找到src.zip - 有趣的是看到里面有3个类的Hashtable.java,没有像1.1中引入的内部类。)

这种设计鼓励继承Hashtable从其功能中受益,但应该优先考虑组合。我找到了bug entry特定于Hashtable的子类(虽然不是关于线程安全性),其中Josh Bloch说:

  

使用委托而不是子类化可以避免这种问题。

在评论中引用@pvg,获得一个很好的总结:

  

一个稍微宽泛的答案是,这基本上是一个90年代早期的设计,它的寿命很长而且显示出来。它是一个通过子类同时尝试既线程安全又可扩展的类,类库在以后的设计迭代中避免使用。

答案 1 :(得分:-1)

这非常简单 - rehash()将重写table字段,因此将它们保存到临时变量以便以后访问。