0

解决以下问题的正确方法是什么?

编写一个逻辑,其中 100 个读取器(Servlet 请求)或一个写入器(Servlet 请求)可以同时访问映射(缓存)中一个键的关键部分。如果在这种情况下写入器进入画面,所有读取器都应该停止进度,并且一旦写入器完成关键部分处理(重新填充同一键的缓存元素),就应该重新启动。

我实现了一个类似这个问题的解决方案,其中一个 Resource 类的实例将与单个键相关联。

class Resource {
  private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
  private final Lock rlock = lock.readLock();
  private final Lock wlock = lock.writeLock();

  void read() { ... /* caller has to hold the read lock */ ... }
  void write() { ... /* caller has to hold the write lock */ ... }

  Lock readLock() { return rlock; }
  Lock writeLock() { return wlock; }
}

以前我使用信号量实现了简单的逻辑,其中我将一个信号量实例与单个键相关联并使用了 100 个许可,如果在这种情况下写入线程进入图片,我消耗了所有剩余的许可(drainPermits)并让所有许可免费所有读取器和写入器线程都在等待队列中。但它导致作家挨饿。

我认为使用 ConcurrentHashMap 可以解决的其他事情?由于 ConcurrentHashMap 在内部具有基于键的锁定(段)。

4

1 回答 1

0

您不必向资源的用户公开锁定,但是如果您开始实现该模式,您很快就会发现您还可以使用实际上为同步访问优化的 ConcurrentHashMap

class Resource {
  private Cache<Key, Value> yourcache;
  private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
  private final Lock rlock = lock.readLock();
  private final Lock wlock = lock.writeLock();

  Value read(Key key) { try {
rlock.lock();
return yourcache.get(key)
} finally {
rlock.unlock();
}
}
  void write(Key key) { ... /* similar pattern to above */ ... }

  Lock readLock() { return rlock; } //don't expose these at all!
  Lock writeLock() { return wlock; }//don't expose these at all!
}
于 2019-07-02T10:32:41.607 回答