使用ReentrantReadWriteLock时需要锁定降级

时间:2018-01-20 16:25:44

标签: java reentrantreadwritelock

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

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 data更改为volatile Object data,我是否还需要降级写锁定才能读锁定?

更新

我的意思是如果我将volatile添加到data,在finally块中发布注释A的写锁之前,我是否还需要获取读取内容锁定为评论BC的代码吗?或者代码可以利用volatile

1 个答案:

答案 0 :(得分:2)

不,无论你是否降级都不需要date_create TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, (锁定已经保证了对volatile的线程安全访问)。

您正在谈论需要降级,这是一件坏事。你可以保持写锁定而不是降级,事情就可以了。当读锁定就足够时,你只是保持一个不必要的强锁。

您不需要降级到读取锁定,但如果您不这样做会降低您的代码效率:如果data需要2秒(很长一段时间) ,然后在没有锁定降级的情况下,每次刷新缓存时都会阻止所有其他读取器2秒钟。

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

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

  • 一个或多个线程位于use(data),具有读锁
  • 一个线程正在刷新缓存,具有写锁定
  • 一个线程在use(data)中没有锁定,一个线程正在使用写锁定刷新缓存