Java 删除并发hashmap中的条目时内存泄漏
假设我们从Java 删除并发hashmap中的条目时内存泄漏,java,memory-leaks,concurrenthashmap,Java,Memory Leaks,Concurrenthashmap,假设我们从ConcurrentHashMap中删除一个条目。ConcurrentHashMap中的删除操作将克隆必须删除的节点之前的节点 现在我的问题是Java如何垃圾收集必须删除的节点之前的原始节点 假设1-->2-->3-->4-->5-->6是由ConcurrentHashMap维护的哈希条目列表。现在我们要删除3 以下代码是JavaConcurrentHashMap HashEntry newFirst = e.next; for (HashEntry p = first; p != e
ConcurrentHashMap
中删除一个条目
。ConcurrentHashMap
中的删除操作将克隆必须删除的节点之前的节点
现在我的问题是Java如何垃圾收集必须删除的节点之前的原始节点
假设1
-->2
-->3
-->4
-->5
-->6
是由ConcurrentHashMap
维护的哈希条目列表。现在我们要删除3
以下代码是JavaConcurrentHashMap
HashEntry newFirst = e.next;
for (HashEntry p = first; p != e; p = p.next) {
newFirst = new HashEntry(p.key, p.hash, newFirst, p.value);
tab[index]= newFirst;
}
- 第一次迭代后
-->1
-->2
-->3
-->4
-->5
6
-->1A
-->2A
-->4
-->5
将创建一个新节点6
,该节点将指向1A
。 原始节点4
仍指向节点3
。 因此,节点4
由2个节点指向4
- 第二次迭代后
-->1
-->2
-->3
-->4
-->5
6
-->1A
-->2A
-->4
-->5
节点6
现在是指向两个列表的指针(4
-->1
-->2
)和(3
-->1A
)。节点2A
(4
-->1
-->2
)之前的原始节点永远不会从哈希项列表中删除3
这不是内存泄漏的情况吗。GC将如何收集(
1
-->2
-->3
),因为它们仍然被ConcurrentHashMap
引用?我认为您误读了该代码。首先,循环如下所示:
HashEntry newFirst = e.next; // the element after the deleted one, in our case: 4
for (HashEntry p = first; p != e; p = p.next) {
newFirst = new HashEntry(p.key, p.hash, newFirst, p.value);
}
tab[index]= newFirst; // this is outside the loop
Step 0: tab[index] --> 1 --> 2 --> 3 --> 4 --> 5 --> 6
newFirst ----------------------^
Step 1: tab[index] --> 1 --> 2 --> 3 --> 4 --> 5 --> 6
newFirst --------------> 1A ---^
Step 2: tab[index] --> 1 --> 2 --> 3 --> 4 --> 5 --> 6
newFirst -------> 2A --> 1A ---^
Step 3: tab[index] --> 2A--> 1A--> 4 --> 5 --> 6
1 --> 2 --> 3 ----^
其次,这是一个单链表,因此迭代如下:
HashEntry newFirst = e.next; // the element after the deleted one, in our case: 4
for (HashEntry p = first; p != e; p = p.next) {
newFirst = new HashEntry(p.key, p.hash, newFirst, p.value);
}
tab[index]= newFirst; // this is outside the loop
Step 0: tab[index] --> 1 --> 2 --> 3 --> 4 --> 5 --> 6
newFirst ----------------------^
Step 1: tab[index] --> 1 --> 2 --> 3 --> 4 --> 5 --> 6
newFirst --------------> 1A ---^
Step 2: tab[index] --> 1 --> 2 --> 3 --> 4 --> 5 --> 6
newFirst -------> 2A --> 1A ---^
Step 3: tab[index] --> 2A--> 1A--> 4 --> 5 --> 6
1 --> 2 --> 3 ----^
(步骤0是初始状态,步骤1和2是循环的两次迭代,步骤3是tab[index]=newFirst
)
如您所见,在步骤3之后,没有任何东西指向1
,因此它符合GC的条件,因此2
和3
p.s.:还要注意新列表中
2A
和1A
的顺序是如何颠倒的。除非有太多的冲突,否则这不会产生实际影响,但在这种情况下,冲突本身是一个比这带来的轻微时间不一致更大的问题。-->感谢您的快速帮助,并为错误放置for循环的“}”括号表示歉意。实际上,我想在for循环之后提到tab[index]=newFirst。我不明白的是1、2和3将如何被垃圾收集。但是你的评论**粗体“正如你所看到的,在第3步之后,没有任何东西指向1,因此它符合GC,因此,2和3**粗体解释了一切。现在我可以理解2和3是如何符合GC的。非常感谢你的简单解释。