在同一个try块中锁定多个ReentrantReadWriteLock是否安全?

2024-03-23

假设我有两个关键资源: foo 和 bar。我用一些东西来保护他们ReentrantReadWriteLock http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.htmls

ReentrantReadWriteLock foo = new RRWL() ...
ReentrantReadWriteLock bar = new RRWL() ...

大多数操作仅使用 foo 或 bar,但有些操作恰好同时使用两者。现在,当使用单个锁时,你不能这样做:

void foo() {
   foo.writeLock().lock();
   privateWorkOnFoo();
   foo.writeLock().unlock();
}

如果抛出异常,你的 foo 将被永远锁定。相反,你把它包裹起来,就像

void foo() {
    try {
        foo.writeLock().lock();
        privateWorkOnFoo();
    } finally { foo.writeLock().unlock(); }
}

但如果我需要同时处理这两方面怎么办?将它们放在一个区块中安全吗?

Option 1

try {
    foo.writeLock().lock();
    bar.writeLock().lock();
    magic();
} finally { 
    bar.writeLock().unlock();
    foo.writeLock().unlock();
}

或者是否有必要为每个锁提供自己的块:

Option 2

try {
    foo.writeLock().lock();
    try {
        bar.writeLock().lock();
        magic();
    } finally { 
      bar.writeLock().unlock();
    }
    
} finally { 
    foo.writeLock().unlock();
}

我不可能是第一个对此进行调查的人……我知道选项 2 是“防弹”的,但它也需要大量的维护工作。选项1可以接受吗?


选项 1 很好。它被称为两锁变体。如果您查看 LinkedBlockingQueue 操作(例如删除),它会锁定 putLock 和 takeLock。以下是 JDK 功能的示例:

  public boolean remove(Object o) {
       if (o == null) return false;
       fullyLock();
       try
       {
       // ...
       }   
       finally {
         fullyUnlock();
       }
    }

   /**
     * Lock to prevent both puts and takes.
     */
    void fullyLock() {
        putLock.lock();
        takeLock.lock();
    }

    /**
     * Unlock to allow both puts and takes.
     */
    void fullyUnlock() {
        takeLock.unlock();
        putLock.unlock();
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在同一个try块中锁定多个ReentrantReadWriteLock是否安全? 的相关文章

随机推荐