Java 我应该在引用队列上同步吗?
我正在查看Java 我应该在引用队列上同步吗?,java,concurrency,Java,Concurrency,我正在查看WeakHashMap的源代码,无意中发现了以下内容: private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); private void expungeStaleEntries() { for (Object x; (x = queue.poll()) != null; ) { synchronized (queue) { /* sn
WeakHashMap
的源代码,无意中发现了以下内容:
private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
private void expungeStaleEntries() {
for (Object x; (x = queue.poll()) != null; ) {
synchronized (queue) {
/* snip */
}
}
}
private final ReferenceQueue=new ReferenceQueue();
私人作废删除登记(){
对于(对象x;(x=queue.poll())!=null;){
已同步(队列){
/*剪断*/
}
}
}
为什么此方法在引用队列
上同步?它本身并不声称是线程安全的:
与大多数集合类一样,该类不同步。A.
同步WeakHashMap可以使用
Collections.synchronizedMap方法
这让我相信,这个实现细节在某种程度上是为了确保引用队列
本身的线程安全(因为GC将从自己的线程
对其进行修改)。但是,没有提到任何关于并发性的问题,并且查看ReferenceQueue
的源代码可以发现它本身甚至没有同步(它使用内部锁)
为什么WeakHashMap
正在其ReferenceQueue
上同步?每次使用ReferenceQueue
时,我是否应该对其进行同步?如果查看,您会发现它明确支持平台内部的线程,因为它声明remove()
方法将阻塞,直到有新条目可用
您在WeakHashMap
中看到的synchronized
是关于确保访问ReferenceQueue
的多个线程正确同步
你可能会发现这一点很有趣
为了回答您的问题,我认为如果您确保只有单个线程访问
ReferenceQueue
,则不需要对其进行外部同步。我不会使用(也想不到一个好的理由)将一个引用队列作为来自多个线程的消费者使用。+1很好的发现-一个读取方法如何修改映射很有趣。@andersoj啊,那个错误报告说得很清楚。由于在WeakHashMap
上调用size
可能会修改基础映射,因此同时调用size
的用户可能会无意中损坏它。这种行为与大多数(所有?)其他JDKMap
实现相反,后者允许多个线程毫无问题地读取其内容,因此,他们决定使该类稍微具有线程安全性,以保持与Map
规范的一致性。@例如,John Vint LinkedHashMap get修改映射,因为它存储访问顺序