据说,那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
? 但如何能等待那么一个信号? 如果还aquires一个writeLock
又在哪里是至上FO读/写锁?
如何保证,如果他们只保护在读取过程中所需的变量不会改变writeLock
?
QUEUES不匹配任务
这是关于这个问题ReentrantReadWriteLock
。
该的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
}
为完整起见,每个解锁()应该是当然在最终块。
但是,如何写一个阅读器? 如果它仅获得readLock? 但如何能等待那么一个信号? 如果还aquires一个writeLock又在哪里是至上FO读/写锁?
我切换到使用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
应该很好地工作。
你不能达到使用具有阻断行为原语非阻塞的行为。 如果你真的想要的作家“写,从来没有等待任何人”,他甚至不应该知道你mentionned存在的锁。
当你执行
rwl.writeLock().lock();
如果有读者操作,笔者将等待。
你应该尝试使用免费的等待(至少无锁)原语,如果你要尊重“永远等待”状态。 例如,使用的ConcurrentLinkedQueue和锁定机构将只用于管理阅读器之间的竞争条件。
你需要的是LinkedBlockingQueue
它提供两个单独的锁 takeLock
和putLock
。
Offer
, put
排队的方法总是使用putLock
其中作为take
方法总是使用takeLock