2

ReentrantReadWriteLock 的文档中有一个关于锁降级的示例用法(请参阅)。

class CachedData {
    final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    Object data;
    volatile boolean cacheValid;

    void processCachedData() {
        rwl.readLock().lock();
        if (!cacheValid) {
            // Must release read lock before acquiring write lock
            rwl.readLock().unlock();
            rwl.writeLock().lock();
            try {
                // Recheck state because another thread might have
                // acquired write lock and changed state before we did.
                if (!cacheValid) {
                    data = ...
                    cacheValid = true;
                }
                // Downgrade by acquiring read lock before releasing write lock
                rwl.readLock().lock();//B
            } finally {//A
                rwl.writeLock().unlock(); // Unlock write, still hold read
            }
        }
        try {
            use(data);
        } finally {//C
            rwl.readLock().unlock();
        }
    }
}

如果我更改Object datavolatile Object data,我是否还需要将写锁降级为读锁?


更新

我的意思是,如果我添加volatiledata,在我finally在评论中释放块中的写锁之前A,我是否还需要获取读锁作为评论中的代码BC做?或者代码可以利用volatile

4

1 回答 1

3

不,volatile无论您是否降级都不需要(锁定已经保证了对 的线程安全访问data)。它也无助于atomicity,这就是 acquire-read-then-write-lock 模式所做的(这也是问题的重点)。

您正在谈论需要降级,就像这是一件坏事。您可以保持写锁定而不是降级,一切都会正常工作。当读锁就足够时,您只是保留了不必要的强锁。

您不需要降级为读锁,但如果您不这样做,它会使您的代码效率降低:如果use(data)需要 2 秒(很长时间),那么如果不降级,您将阻止所有其他阅读器 2每次刷新缓存的秒数。

如果您的意思是为什么在缓存刷新完成后您甚至需要读锁,那是因为否则在我们仍在工作时另一个线程可能会启动新的缓存刷新(因为不会有任何锁)上use(data)

在给定的示例代码中,由于没有足够的信息,无法确定它是否真的重要,但它会为该方法创建一个可能的附加状态,这不是一个优势:

  • 一个或多个线程在use(data),有读锁
  • 一个线程正在刷新缓存,有写锁
  • 一个线程处于use(data)无锁状态,一个线程正在使用写锁刷新缓存
于 2018-01-20T17:03:34.473 回答