解决以下问题的正确方法是什么?
编写一个逻辑,其中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具有基于密钥的内部锁定(段)。
答案 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!
}