我应该在ReferenceQueue上同步吗?

时间:2012-05-14 22:23:34

标签: java concurrency

我正在查看WeakHashMap的源代码,并偶然发现了这一点:

private final ReferenceQueue<Object> queue = new ReferenceQueue<>();

private void expungeStaleEntries() {
    for (Object x; (x = queue.poll()) != null; ) {
        synchronized (queue) {
           /* snip */
        }
    }
}

为什么此方法会在ReferenceQueue上同步? WeakHashMap本身并不声称线程安全:

  

与大多数集合类一样,此类未同步。一个   可以使用。来构造同步的WeakHashMap   Collections.synchronizedMap方法。

这使我相信这个实现细节是以某种方式确保ReferenceQueue本身的线程安全(因为GC将从它自己的Thread修改它)。但是,the documentation for ReferenceQueue没有提及任何并发问题,并且查看ReferenceQueue的源代码表明它甚至没有自身同步(它使用内部锁)。

为什么WeakHashMap在其ReferenceQueue上进行同步?我每次使用它时都应该ReferenceQueue进行同步吗?

1 个答案:

答案 0 :(得分:6)

如果查看ReferenceQueue,您会看到它明确支持平台内的线程,因为它声明remove()方法将阻塞,直到新条目可用。

您在synchronized中看到的WeakHashMap是关于确保访问ReferenceQueue的多个线程正确同步。

您可能会发现此相关的bug at bugs.sun.com很有趣。

要回答您的问题,我认为如果您确保仅由单个线程访问,则不需要ReferenceQueue的外部同步。我不会使用(并且不能想出一个好的理由)将单个ReferenceQueue用作来自多个线程的消费者。