我正在查看源代码,WeakHashMap并偶然发现:
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
private void expungeStaleEntries() {
for (Object x; (x = queue.poll()) != null; ) {
synchronized (queue) {
/* snip */
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么这个方法同步ReferenceQueue?WeakHashMap本身并不声称是线程安全的:
与大多数集合类一样,此类不同步.可以使用Collections.synchronizedMap方法构造同步的WeakHashMap.
这使我相信这个实现细节是以某种方式确保ReferenceQueue自身的线程安全(因为GC将自己修改它Thread).但是,文档ReferenceQueue中没有提到任何关于任何并发问题的内容,并且看一下源代码,ReferenceQueue发现它甚至没有自身同步(它使用内部锁).
为什么WeakHashMap同步它ReferenceQueue呢?我ReferenceQueue每次使用它时都应该同步吗?
如果您看一下,ReferenceQueue您将看到它明确支持平台内的线程,因为它声明该remove()方法将阻塞,直到有新条目可用.
在synchronized你看到的WeakHashMap就是要确保多线程访问ReferenceQueue进行正确的同步.
您可能会在bugs.sun.com上发现此相关错误.
要回答您的问题,我认为ReferenceQueue如果您确保仅由单个线程访问,则不需要外部同步.我不会使用(并且不能想到一个很好的理由)将单个ReferenceQueue作为来自多个线程的消费者使用.