如你所见,读重进入只有在当前没有线程对资源进行写操作时才可能被允许。另外,假如调用线程对象已经有了读访问权限,那么它的读重进入优先级将高于任何写访问请求。
写的重进入
写的重进入只有在调用线程对象已经拥有了写访问权限时才是被允许的。下面是修改了lockWrite()和unlockWrite()之后的代码:
public class ReadWriteLock{
private Map
readingThreads =
new HashMap
(); private int writeAccesses = 0; private int writeRequests = 0; private Thread writingThread = null; public synchronized void lockWrite() throws InterruptedException{ writeRequests++; Thread callingThread = Thread.currentThread(); while(! canGrantWriteAccess(callingThread)){ wait(); } writeRequests--; writeAccesses++; writingThread = callingThread; } public synchronized void unlockWrite() throws InterruptedException{ writeAccesses--; if(writeAccesses == 0){ writingThread = null; } notifyAll(); } private boolean canGrantWriteAccess(Thread callingThread){ if(hasReaders()) return false; if(writingThread == null) return true; if(!isWriter(callingThread)) return false; return true; } private boolean hasReaders(){ return readingThreads.size() > 0; } private boolean isWriter(Thread callingThread){ return writingThread == callingThread; } }
注意当判断调用线程对象是否可以获得写访问权限时,该线程所持有的写操作锁是要被进行计数的。(这句真心觉得真心拗口,不会翻,帖下原句,知道的朋友告诉一下,先谢了! Notice how the thread currently holding the write lock is now taken into account when determining if the calling thread can get write access.)
从读到写的重进入
某些时候一个持有读访问权限的线程需要同时持有写访问权限。这种情况只有在该线程是唯一的读操作者时才是有可能的。为了实现该功能,需要稍微修改一下writeLock()方法,代码如下:
public class ReadWriteLock{
private Map
readingThreads =
new HashMap
(); private int writeAccesses = 0; private int writeRequests = 0; private Thread writingThread = null; public synchronized void lockWrite() throws InterruptedException{ writeRequests++; Thread callingThread = Thread.currentThread(); while(! canGrantWriteAccess(callingThread)){ wait(); } writeRequests--; writeAccesses++; writingThread = callingThread; } public synchronized void unlockWrite() throws InterruptedException{ writeAccesses--; if(writeAccesses == 0){ writingThread = null; } notifyAll(); } private boolean canGrantWriteAccess(Thread callingThread){ if(isOnlyReader(callingThread)) return true; if(hasReaders()) return false; if(writingThread == null) return true; if(!isWriter(callingThread)) return false; return true; } private boolean hasReaders(){ return readingThreads.size() > 0; } private boolean isWriter(Thread callingThread){ return writingThread == callingThread; } private boolean isOnlyReader(Thread thread){ return readers == 1 && readingThreads.get(callingThread) != null; } }
现在ReadWriteLock类是可以“从读到写”重进入了。
从写到读的重进入
某些时候一个已经持有写访问权限的线程需要同时持有读访问权限。一个对操作者线程应该总是可以获取到读访问权限的。如果有一个线程拥有写访问权限,那么其他的线程是不能拥有读访问或写