我正在学习一个教程,它基本上解释了在多线程环境中调整Hashmap大小时发生争用情况的原因:
在Java中,如果同时发现两个线程,则HashMap需要调整大小,并且它们都尝试调整大小。在Java中调整HashMap的大小的过程中,存储在链表中的存储桶中的元素在迁移到新存储桶的过程中顺序颠倒,因为Java HashMap不会在尾部附加新元素,而是在头部附加新元素。避免横越尾巴。如果发生比赛条件,那么您将陷入无限循环
阅读此书后,我有两个问题:
请帮我澄清一下,万分感谢!
实际上,至少有一种与 重新哈希处理 有关的竞赛条件。查看以下代码片段(来自Sun JDK7):
boolean oldAltHashing = this.useAltHashing; this.useAltHashing |= sun.misc.VM.isBooted() && (this.newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD); boolean rehash = oldAltHashing ^ this.useAltHashing; transfer(newTable, rehash); this.table = newTable;
在这里,线程T1最终以rehash = true线程T2最终rehash = false(假设T1已更改的值this.useAltHashing)是可能的。
rehash = true
rehash = false
this.useAltHashing
现在,猜猜哪个线程将编写this.table-您也不知道可以。因此,是否获得一致的内部状态是一个运气问题。
this.table
无论如何,正如我在 设计 评论中提到的那样 ,不应在多线程环境中使用HashMap 。不起作用。因为这个原因或其他原因。以上只是为什么 不应该违反合同的 一个例子 。