有一个共享资源,我们需要按照以下说明对其执行读/写操作:
我已经编写了如下所述的代码,但是此代码的问题是,当单个读取线程获得了锁时,所有读取都会被阻止。此外,我正在考虑使用布尔标志,例如canReadContinue。现在,当read第一次获得锁时,我会将此标志翻转为true,如果为true,则其他线程不应尝试获取该锁。
class SharedResource {
Lock writeLock
public Object read() {
writeLock.acquire()
doRead()
}
public void write(Object toBeWritten) {
writeLock.acquire()
doWrite(toBeWritten)
writeLock.release()
}
}
预计在不进行任何写操作的情况下,多个线程应该能够读取。
更新1:
公共类SharedResource {
private Object writeLock = new Object();
private volatile boolean canReadContinue;
private volatile int readCount;
public void write(Object newState) throws InterruptedException {
synchronized (writeLock) {
// To make sure no read is going on
while (readCount > 0) {
wait();
}
System.out.println("Write thread has the lock.");
doWrite(newState);
}
}
public Object read() {
if(canReadContinue) {
incrementCount();
} else {
synchronized (writeLock) {
System.out.println("Read thread has the lock.");
canReadContinue = true;
incrementCount();
}
}
Object result = doRead();
decrementCount();
if(readCount == 0) {
// TODO - release lock and notify
}
return result;
}
private synchronized void incrementCount() {
readCount++;
}
private synchronized void decrementCount() {
readCount--;
}
private void doWrite(Object newState) {
// do stuff
}
private Object doRead() {
return "";
}
}
现在我需要一种机制来释放“ // TODO-释放锁定并通知”行中的锁定,任何指针如何解决此问题?
答案 0 :(得分:5)
提示:
wait
和notify
。有效地,您需要 1 实施简化版本ReadWriteLock
。
1-...用于作业分配。在现实世界的程序中,您应该简单地使用现有的ReadWriteLock
类。
答案 1 :(得分:0)
我还想使用布尔标志,例如canReadContinue
您在正确的轨道上。但是请记住,任何数量的线程都可以同时执行其 read 访问,并且只有在当前正在读取 no 的其他线程时才能进行写访问。或写作。
因此,您需要跟踪当前有多少个读取器持有该锁,并且每个读取器必须确保完成后释放该锁。仅当&当0个读者(和0个作者)持有锁时,作者才可以继续操作;并且只有当&当0个作者持有锁时,任何读者才可以继续。
答案 2 :(得分:0)
在此处更新代码的答案是您需要完成的一些工作:
public class SharedResource {
private final Object signal = new Object();
private boolean writeLocked;
private int readerCount;
public void write(final Object newState) throws InterruptedException {
this.acquireWriteLock();
try {
// Now we know that no read and no other write is going on.
System.out.println("Write thread has the lock.");
this.doWrite(newState);
} finally {
// make sure we release the lock in any case.
this.realeaseWriteLock();
}
}
private void acquireWriteLock() throws InterruptedException {
synchronized (this.signal) {
// Wait until no more readers *and* no writer holds the lock.
// To do: Insert the condition we need to wait for:
while (/* condition here! */ ) {
// To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
}
this.writeLocked = true; // Let others know that the write lock has been taken.
}
}
private void realeaseWriteLock() {
synchronized (this.signal) {
this.writeLocked = false;
// To do: Notify any and all other waiting threads that we released the lock!
}
}
public Object read() {
// To be done...
}
private void acquireReadLock() throws InterruptedException {
synchronized (this.signal) {
// Wait until no *writer* holds the lock.
// To do: Insert condition we need to wait for:
while (/* condition here! */ ) {
// To do: Wait for the lock-holding thread(s) to signal that they released their lock(s).
}
// Now we know that no writer holds the lock. Acquire (another) read lock:
this.readerCount++;
}
}
private void releaseReadLock() throws InterruptedException {
synchronized (this.signal) {
this.readerCount--;
// To do: Notify any threads waiting (i.e. writer threads).
// (In fact only *required* if there are *no* more readers now because that's the only condition any thread will wait on.)
}
}
private void doWrite(final Object newState) {
// do stuff
}
private Object doRead() {
return "";
}
}
要理解的主要问题可能是,每次尝试进行锁定可能都必须wait
,并且每次释放锁定都应notify
任何(潜在)等待线程。