Общее·количество·просмотров·страницы

Java Dev Notes - разработка на Java (а также на JavaScript/Python/Flex и др), факты, события из АйТи

Архив блога

вторник, 14 сентября 2010 г.

Блокировка чтения/записи. Часть 4

Обработаем случай, когда потоку, который имеет доступ на чтение, вдруг понадобилось получить доступ на запись. Он это сможет сделать, если он является единственным потоком, который осуществляет чтение данных.

В предыдущем посте был рассмотрен случай блокировки, который обрабатывает варианты повторной блокировки для чтения и записи. Возьмем код оттуда и немножко модифицируем.

Введем новый метод - isOnlyReader, который проверяет, является ли текущий поток единственным читающим потоком:

private boolean isOnlyReader(Thread thread){
return readingThreads.size() == 1 && readingThreads.get(thread) != null;
}


Также немножко модифицируем метод canGrantWriteAccess:

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;
}


В остальном, код класса ReadWriteLock такой же, как и в
предыдущем посте. Полный код:

public class ReadWriteLock {
private Map<Thread, Integer> readingThreads = new HashMap<Thread, Integer>();
private int writers = 0;
private int writeRequests = 0;
private Thread writingThread;
 
//
// read locking
//
 
public synchronized void lockRead() throws InterruptedException {
Thread callingThread = Thread.currentThread();
while(!canGrantReadAccess(callingThread)) {
wait();
}
int accessCount = getReadAccessCount(callingThread);
readingThreads.put(callingThread,accessCount+1);
}
 
public synchronized void unlockRead() {
Thread callingThread = Thread.currentThread();
int accessCount = getReadAccessCount(callingThread);
if(accessCount == 1) {
readingThreads.remove(callingThread);
} else {
readingThreads.put(callingThread, accessCount-1);
}
notifyAll();
}
 
private boolean canGrantReadAccess(Thread callingThread) {
if(writers > 0) return false;
if(isReader(callingThread) return true;
if(writeRequests > 0) return false;
return true;
}
 
private int getReadAccessCount(Thread callingThread) {
Integer accessCount = readingThreads.get(callingThread);
if(accessCount == null) return 0;
return accessCount.intValue();
}
 
private boolean isReader(Thread callingThread) {
return readingThreads.get(callingThread) != null;
}
 
private boolean hasReaders() {
return readingThreads.size() > 0;
}
 
private boolean isOnlyReader(Thread thread) {
return readingThreads.size() == 1 && readingThreads.get(thread) != null;
}
 
//
// write locking
//
 
public synchronized void lockWrite() throws InterruptedException {
writeRequests++;
Thread callingThread = Thread.currentThread();
 
while(!canGrantWriteAccess(callingThread)){
wait();
}
writeRequests--;
writers++;
writingThread = callingThread;
}
 
public synchronized void unlockWrite() throws InterruptedException {
writers--;
if(writers == 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 isWriter(Thread callingThread) {
return writingThread == callingThread;
}
}

Комментариев нет:

Отправить комментарий

Постоянные читатели