在javax.swing.plaf.nimbus.ImageCache中使用ReentrantReadWriteLock

时间:2016-02-05 02:22:50

标签: java swing concurrency

在阅读JDK代码时,我试图找到ReentrantReadWriteLock的一些用法,并发现唯一的用法是javax.swing.plaf.nimbus.ImageCache

我在这里使用ReentrantReadWriteLock有两个问题:

我可以理解readLock方法中使用的getImagewriteLock方法中使用的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>) 更多的并发性?

1 个答案:

答案 0 :(得分:1)

第二个问题:

  

ReentrantReadWriteLocks可用于在某些类型的集合的某些用途中提高并发性。这通常是值得的,只有当预期集合很大时,由更多的读取器线程访问而不是编写器线程,并且需要具有超过同步开销的开销的操作。 - 来自ReentrantReadWriteLock Documentation

上面提到的所有要点都对应于图像缓存。至于“为什么不使用ConcurrentHashMap?” - ImageCache使用没有并发实现的LinkedHashMap。有关原因的推测,请参阅此SO问题:Why there is no ConcurrentLinkedHashMap class in jdk?

第一个问题:

我也怀疑为什么flush方法不像writeLock方法那样使用setImage。毕竟它在结构上修改了地图。

在审核了javax.swing.plaf.nimbus.ImageCachePixelCountSoftReference来源以及ReentrantReadWriteLockLinkedHashMap文件后,我没有得到明确的答案。 虽然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发送电子邮件会得到一个答案,我不确定该怎么做。

希望有人会出现并提供实际答案。好问题。