Servlet请求的Java并发问题

时间:2019-07-02 07:04:05

标签: java concurrency readerwriterlock

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

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

我实现了解决方案like in this question之一,其中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具有基于密钥的内部锁定(段)。

1 个答案:

答案 0 :(得分: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!
}