Пакет java . uti . concurrent . locks
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

В Java SE 5.0 появился класс java . uti . concurrent . locks . ReentrantLock, конструирующий реентерабельную блокировку, которая может быть испаользована для защиты критичной части кода.

private Lock myLock = new ReentrantLock(); // ReentrantLock реализует интерфейс Lock

myLock . lock ();

try {

// критичный раздел

}

finally {

myLock . unlock (); // гарантирует разблокировку даже в случае возникновения исключения

}

Такая конструкция гарантирует, что только один поток в единицу времени сможет войти в критичный раздел кода. Как только один поток блокирует объект блокировки, никакой другой поток не сможет выполнить оператор lock. Когда другие потоки попытаются это сделать, они будут деактивированы до тех пор, пока первый поток не снимет блокировку с этого объекта. Важно, чтобы операция unlock помещалась в конструкцию finally. Если код критичного раздела сгенерирует исключение, блокировка должна быть снята. В противном случае другие потоки будут заблокированы навсегда.

Блокировка называется реентерабельной, потому что поток может повторно захватывать блокировку, которой он уже владеет. Объект блокировки имеет счетчик блокировок, отслеживающий вложенные вызовы метода lock(). Поток должен вызвать unlock() для каждого вызова lock(), чтобы, в конце концов, снять блокировку.

Поток блокируется навечно, когда он вызывает метод lock() для захвата блокировки, которой владеет другой поток. Поэтому следует быть осторожным, пытаясь захватить блокировку. Метод tryLock() пытается захватить блокировку и возвращает true, если ему это удается. Иначе возвращается false и тогда можно переключить поток на что-нибудь другое.

i f ( myLock . tryLock ())

// теперь поток владеет блокировкой

try {

// …

}

finally { myLock . unlock ();}

else

// делать что-то другое

Пример

public boolean impendingBow(Friend bower) {

Boolean myLock = false;

Boolean yourLock = false;

try {

myLock = lock.tryLock();

yourLock = bower.lock.tryLock();

} finally {

if (!(myLock && yourLock)) {

if (myLock) {

   lock.unlock();

}

if (yourLock) {

   bower.lock.unlock();

   } } }

return myLock && yourLock;

}

Пакет java . uti l. concurrent . locks определяет два класса блокировок – ReentrantLock и ReentrantReadWriteLock . Последний удобен, когда есть много потоков, читающих структуру данных, и поменьше потоков – модифицирующих её. В такой ситуации имеет смысл разрешить разделенный доступ читателям. Конечно, поток-писатель должен по-прежнему иметь исключительный доступ. Ниже описаны шаги, необходимые для использования блокировок чтения/записи.

1. Сконструировать объект ReentrantReadWriteLock:
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

2. Извлечь блокировки чтения и записи:
private Lock readLock = rwl.readLock(); // получает блокировку чтения, которая может быть захвачена многими читателями, но исключая всех писателей.
private Lock writeLock = rwl.writeLock(); // получает блокировку записи, исключающую доступ всех читателей и писателей.

3. Использовать блокировку чтения для всех читателей:
public double getTotalBalance (){
readLock . lock ();
try {…}
finally { readLock . unlock ();}
}

4. Использовать блокировку записи для всех, кто изменяет данные:
public void transfer (…){
writeLock . lock ();
try {…}
finally { writeLock . unlock ();}
}

Пример

public class Dictionary {

private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

private final Lock read = readWriteLock.readLock();

private final Lock write = readWriteLock.writeLock();

private HashMap<String, String> dictionary = new HashMap<String, String>();

public void set(String key, String value) {

write.lock();

try { dictionary.put(key, value); } finally { write.unlock(); }

}

public String get(String key) {

read.lock();

try{ return dictionary.get(key); } finally { read.unlock(); }

}

public String[] getKeys() {

read.lock();

  try {

String keys[] = new String[dictionary.size()];

return dictionary.keySet().toArray(keys);

} finally { read.unlock(); }

} }














Дата: 2019-02-19, просмотров: 218.