在阅读JDK代码时,我试图找到ReentrantReadWriteLock
的一些用法,并发现唯一的用法是javax.swing.plaf.nimbus.ImageCache
。
我在这里使用ReentrantReadWriteLock
有两个问题:
我可以理解readLock
方法中使用的getImage
和writeLock
方法中使用的setImage
,但为什么readLock
用于flush
flush
方法? public void flush() {
lock.readLock().lock();
try {
map.clear();
} finally {
lock.readLock().unlock();
}
}
方法也不是某种"写",因为它改变了地图:
ConcurrentHashMap
另一个问题:为什么不在这里使用mapEntries
,因为它会为不同的ReadWriteLock
提供一些并发写入,并提供比numpy.fromiter((<some_func>(x) for x in <something>),<dtype>,<size of something>)
更多的并发性?
答案 0 :(得分:1)
ReentrantReadWriteLocks
可用于在某些类型的集合的某些用途中提高并发性。这通常是值得的,只有当预期集合很大时,由更多的读取器线程访问而不是编写器线程,并且需要具有超过同步开销的开销的操作。 - 来自ReentrantReadWriteLock Documentation
上面提到的所有要点都对应于图像缓存。至于“为什么不使用ConcurrentHashMap
?” - ImageCache
使用没有并发实现的LinkedHashMap
。有关原因的推测,请参阅此SO问题:Why there is no ConcurrentLinkedHashMap class in jdk?
我也怀疑为什么flush
方法不像writeLock
方法那样使用setImage
。毕竟它在结构上修改了地图。
在审核了javax.swing.plaf.nimbus.ImageCache
和PixelCountSoftReference
来源以及ReentrantReadWriteLock
和LinkedHashMap
文件后,我没有得到明确的答案。
虽然flush
使用readLock
让我感到困惑,但由于ReentrantReadWriteLock's
文档有以下示例,因此在清除writeLock
时会使用TreeMap
。
// For example, here is a class using a TreeMap that is expected to be
// large and concurrently accessed.
class RWDictionary {
private final Map<String, Data> m = new TreeMap<String, Data>();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock w = rwl.writeLock();
// other code left out for brevity
public void clear() {
w.lock(); // write lock
try { m.clear(); } // clear the TreeMap
finally { w.unlock(); }
}
}
我唯一能做的就是推测。
<强>猜测:强>
ImageCache
代码并且知道何时以及如何(不)使用flush
方法的人。这也不太可能。通过电子邮件询问作者为何使用readLock
代替writeLock
会很有趣,但源中没有列出作者或电子邮件。也许向Oracle发送电子邮件会得到一个答案,我不确定该怎么做。
希望有人会出现并提供实际答案。好问题。