我在许多教程中遇到过ReadWriteLock的非重入实现。
public class ReadWriteLock{
private int readers = 0;
private int writers = 0;
private int writeRequests = 0;
public synchronized void lockRead() throws InterruptedException{
while(writers > 0 || writeRequests > 0){
wait();
}
readers++;
}
public synchronized void unlockRead(){
readers--;
notifyAll();
}
public synchronized void lockWrite() throws InterruptedException{
writeRequests++;
while(readers > 0 || writers > 0){
wait();
}
writeRequests--;
writers++;
}
public synchronized void unlockWrite() throws InterruptedException{
writers--;
notifyAll();
}
}
问题:
此类的对象(比如lock
)在所有读写器线程中共享以进行同步。
让我们假设Reader T1调用lock.lockRead()
,这将锁定锁定对象,而Reader T2同时调用同一对象上的lockRead()
。但T1已经锁定了对象,因此T2应该被阻塞并在队列中等待。
那么,代码如何允许多个读者同时设置readLock?
当我弄错了时,请纠正我。
答案 0 :(得分:2)
确实没有2个线程可以同时执行lockRead()
方法的 body 。但是,读取器/写入器模式无需正常工作并具有预期的性能。
重要的是,如果没有活动的作者(lockRead()
未被调用),wait
方法会快速返回。方法结束时释放锁定,从而允许另一个线程获取读锁定。
所以,是的,获取读锁定(递增readers
)的行为是序列化的。但它发生得太快了,它运作得很好。
举例说明:
private ReadWriteLock lock = new ReadWriteLock(); // this instance is shared by all threads
public void ReadSomething() {
try {
lock.lockRead(); // serialized, but very quick
PerformWork(); // potentially slower, but is concurrent
} finally {
lock.unlockRead(); // serialized, but very quick
}
}
如果2个线程试图在同一时间运行上述ReadSomething()
方法,那么一次只能有一个线程能够执行lock.lockRead()
。但是只要该方法返回其中一个线程,第二个线程就能够执行它。对lock.lockRead()
的调用发生得如此之快,以至于你甚至无法注意到一个线程在等待另一个线程。
重要的是,两个线程都能够同时执行更耗时的PerformWork()
。