据说,ReentrantReadWriteLock是为一位作家和多位读者设计的。
然而,读取器应该等到缓冲区中出现一些数据。
那么,该锁什么?
我创建了如下并发对象:
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
protected final Lock readLock = rwl.readLock();
protected final Lock writeLock = rwl.writeLock();
protected final Condition hasData = writeLock.newCondition();现在,在写方法中,我这样做:
writeLock.lock();
// writing first portion and updating variables
hasData.signalAll();
// if required then writing second portion and updating variables
hasData.signalAll();但是如何写一个读者呢?它应该只收购readLock吗?但它怎么能等待信号呢?如果它也拥有一个writeLock,那么读/写锁的优势在哪里?
如果只受writeLock保护,如何确保所需变量在读取过程中不会更改?
队列与任务不匹配
这是关于ReentrantReadWriteLock的问题。
发布于 2012-10-26 15:01:08
ReentrantReadWriteLock确实有点混乱,因为readLock没有条件。您必须在读取器中升级到writeLock才能等待情况的发生。
在作家身上。
writeLock.lock(); //locks all readers and writers
// do write data
hasData.signalAll();
writeLock.unlock();在读者中,你会:
readLock.lock(); //blocks writers only
try{
if(!checkData()) //check if there's data, don't modify shared variables
{
readLock.unlock();
writeLock.lock(); // need to lock the writeLock to allow to use the condition.
// only one reader will get the lock, other readers will wait here
try{
while(!checkData()) // check if there' still no data
{
hasData.await(); //will unlock and re-lock after writer has signalled and unlocked.
}
readLock.lock(); // continue blocking writer
}
finally
{
writeLock.unlock(); //let other readers in
}
}
//there should be data now
readData(); // don't modify variables shared by readers.
}
finally
{
readlock.unlock(); //let writers in
}当然,为了完整性,每个解锁()都应该位于一个最终块中。
发布于 2012-10-26 14:10:53
但是如何写一个读者呢?它应该只收购readLock吗?但它怎么能等待信号呢?如果它也拥有一个writeLock,那么读/写锁的优势在哪里?
我会切换到使用一个BlockingQueue来处理所有这些问题。您的读者可以调用queue.take(),哪些块等待队列中的元素。
你的作家有点复杂。我要做的事情如下:
// initially try to put an element into the queue
if (!queue.offer(element)) {
// if the queue is full then take an element off the head and just drop it
// this won't block and may not remove anything due to race conditions
queue.poll();
// this put will never block because now there will be space in the queue
queue.put(element);
}如果有多个作者,这是行不通的。那么你需要一个synchronized锁。如果您处理的是一个固定大小的队列,那么ArrayBlockingQueue应该工作得很好。
发布于 2012-10-26 14:08:37
不能使用具有阻塞行为的原语来实现非阻塞行为。如果你真的想让作者“写作,从不等待任何人”,他甚至不应该知道你提到的锁是存在的。
当你执行
rwl.writeLock().lock();如果有读者在操作,作者会等待。
如果您想要尊重“永不等待”条件,您应该尝试使用无等待(至少是无锁)原语。例如,使用ConcurrentLinkedQueue和锁定机制,这将只用于管理读取器之间的争用条件。
https://stackoverflow.com/questions/13088363
复制相似问题