为什么Java的Cleaner使用链表而不是ConcurrentHashSet?

问题描述 投票:0回答:1

Java 的

Cleaner
在底层使用双向链表来保存
PhantomReference
,直到它们的所指对象变得虚拟可达。当
Cleaner
的守护线程弹出并从其
PhantomReference
中删除一个
ReferenceQueue
并将其从列表中删除时,整个列表必须被锁定(删除代码为列表中的
@synchronized
)。

相比之下,

ConcurrentHashMap
仍然可以提供对
PhantomReference
的O(1)访问,而且还可以通过让多个清理线程同时从映射中删除
PhantomReference
(作为键)来支持并发修改。

Java 采用双向链表方法有什么原因吗?是因为

Cleaner
仅使用单个守护线程进行清理,所以缺乏并发性并不重要吗?还是有更深层的原因?

java concurrenthashmap phantom-reference
1个回答
0
投票

使用双向链表的性能比使用

ConcurrentHashMap
要好得多,因为清理器与双向链表的节点对象一起工作。

删除节点只是调整链表中的两个指针(一个来自前一个节点,一个来自下一个节点)和调整当前节点中的两个指针(将其标记为已删除)。其源代码有12行代码(https://github.com/openjdk/jdk21u/blob/master/src/java.base/share/classes/jdk/internal/ref/PhantomCleanable.java#L101 ).

将这 12 行与

ConcurrentHashMap
删除单个条目所需执行的工作进行比较(https://github.com/openjdk/jdk21u/blob/master/src/java.base/share/classes/java/ util/concurrent/ConcurrentHashMap.java#L1110):超过 70 行代码,而且代码更复杂。

这两个操作都是 O(1),但这并不意味着

ConcurrentHashMap
需要相同的时间 - 它只意味着在这两种数据结构中,当包含更多数据时,运行时间不会增加。

© www.soinside.com 2019 - 2024. All rights reserved.