java - 从写入器向读取器发送信号时正确使用 ReentrantReadWriteLock?

标签 java multithreading concurrency reentrantreadwritelock

使用模式产生的原因如下:

  1. 如果条件不存在,我需要读取线程来等待数据。

  2. 读锁不支持条件,因此条件应从写锁中获取。

  3. 由于读线程会等待条件,因此它也应该获取写锁来等待。

我在类里面有以下锁定义:

private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
protected final Lock readLock = rwl.readLock();
protected final Lock writeLock = rwl.writeLock();
protected final Condition hasData = writeLock.newCondition();

在我的编写方法中,我有以下模式:

try {
   writeLock.lock();    

   //...

   if( something_written ) {
      hasData.signalAll();
   }

}
finally {
   writeLock.unlock();
}

在我的阅读方法中,我有以下模式

try {
   readLock.lock();    

   while( data_absent ) {

      // I need to acquire write lock to wait for condition!
      try {

          // first releasing read lock since we can't acquire write lock otherwise
          // unfortunately this won't release a lock if it was acquired more than once (reentrant)
          readLock.unlock();

          // acquiring write lock to wait it's condition
          writeLock.lock();
          hasData.await(1000, TimeUnit.MILLISECONDS);
      }
      finally {

          // releasing write lock back
          writeLock.unlock();

          // reacquiring read lock
          // again see note about reentrancy
          readLock.lock();
      }


   }

   // reading

}
finally {
   readLock.unlock();
}

上面的模式正确吗?

问题在于,如果 reader 是可重入的,即多次锁定读取,则释放代码将不起作用,并且 reader 会卡在获取写锁的行。

最佳答案

这听起来像是一个经典的生产者/消费者模式,因此我建议您为此目的查看现有的数据结构,例如 BlockingQueue 中的一个。实现。

生产者线程put()将数据放入队列,消费者线程take()将数据从队列中取出。

手动同步/锁定应该始终是最后的手段。

关于java - 从写入器向读取器发送信号时正确使用 ReentrantReadWriteLock?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14279765/

相关文章:

c++ - 哪些 std::async 实现使用线程池?

data-structures - 解释 Michael & Scott 无锁队列算法

java - 编程难题 : how to count number of bacteria that are alive?

java - Kafka Log4j 附加程序中的延迟

java - 如何在java中调用带有结果集、输入、输出参数的SQL Server存储过程?

java - Spring Data JPA 忽略 FetchMode

多线程条件变量

java - JVM 在不牺牲性能的情况下可以同时持有的锁数量

multithreading - Web-Wokers,并发还是并行?

ios - NSOperation 与 Grand Central Dispatch