【问题标题】:java multiple writers and multiple readers locksjava多写多读锁
【发布时间】:2021-03-08 15:32:23
【问题描述】:

我正在尝试实现一个遵循以下约束的系统:

  • 我有一个共享资源,例如原子数组
  • 我想同时支持从阵列中进行多次读取。
  • 我想同时支持对数组的多次写入
  • 我不希望读取和写入操作同时发生。

我发现 [this][1] stackoverflow post 关于类似的目标,但我认为建议的解决方案是允许同时读取和写入:

Class ReadAndWrite {
 private ReentrantLock readLock;
 private ReentrantLock writeLock;
 private AtomicInteger readers;
 private AtomicInteger writers;
 private File file;

 public void write() {
   if (!writeLock.isLocked()) {
    readLock.tryLock();
    writers.incrementAndGet(); // Increment the number of current writers
    // ***** Write your stuff *****
    writers.decrementAndGet(); // Decrement the number of current writers
    if (readLock.isHeldByCurrentThread()) {
     while(writers != 0); // Wait until all writers are finished to release the lock
     readLock.unlock();
    }
   } else {
     writeLock.lock();
     write();
   }
  }

 public void read() {
   if (!readLock.isLocked()) {
    writeLock.tryLock();
    readers.incrementAndGet(); 
    // ***** read your stuff *****
    readers.decrementAndGet(); // Decrement the number of current read
    if (writeLock.isHeldByCurrentThread()) {
     while(readers != 0); // Wait until all writers are finished to release the lock
     writeLock.unlock();
    }
   } else {
     readLock.lock();
     read();
   }
  }

在我看来,这段代码允许同时读取和写入,例如:两个线程将尝试同时读取/写入。如果在写/读中,他们每个人都将进入第一个。如何确保写入阻止读取和读取阻止写入? [1]:Multiple readers and multiple writers(i mean multiple) synchronization

【问题讨论】:

  • #tryLock 是一个乐观锁,你需要检查返回值以确保你确实获得了锁。如果您因为无法锁定它而想要阻止它,那么您可以调用#lock。另请查看StampedLock
  • 你是对的,读+写可以同时发生。我不确定这是否是最好的方法,但我认为你可以创建第三个锁checkLocks,它总是首先被声明,并在检查并声明其他锁后被释放。

标签: java locks


【解决方案1】:

与其反复检查锁,不如尝试使用它:

private void writeInternal() {
    //thread-unsafe writing code
}

public void write() {
    if (!writeLock.tryLock()) {
        writeLock.lock();
    }
    try {
        this.writeInternal(); //in try-block to ensure unlock is called
    } finally {
        writeLock.unlock();
    }
}

使用 readLock 将是一种类似的方法。您还想确保您真正使用的是读/写锁,而不仅仅是两个单独的锁:

private final ReadWriteLock lock;

public ReadAndWrite() {
    this.lock = new ReentrantReadWriteLock();
}

然后您将通过this.lock.readLock() 等访问读/写锁。

【讨论】:

  • 不确定我是否理解您如何确保读取不会与写入同时发生?为什么突然决定使用 ReadWriteLock ?它允许一次写入而不是多次写入
  • 正如您之前的做法,您一次只能实现 1 次写入,或一次只能实现 1 次读取,但它们并不相互依赖。通常,您可以一次读取任意数量的资源,但是当作者出现时,一切都必须等待;这是基于锁的并发中相当典型的范例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 2020-06-27
  • 2017-06-19
  • 2012-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多