Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 删除并发hashmap中的条目时内存泄漏_Java_Memory Leaks_Concurrenthashmap - Fatal编程技术网

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

以下代码是Java
ConcurrentHashMap

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
    。 因此,节点
    4
    由2个节点指向

  • 第二次迭代后

    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的。非常感谢你的简单解释。