#illegalstateexception
#исключение illegalstateexception
Вопрос:
Несмотря на то, что блокировка удерживается потоком записи, при выполнении указанного ниже кода возникает следующее исключение.
Автор вошел в критическую секцию! Сообщение: оставайтесь сильными, удерживая блокировку боли! Исключение в потоке «Writer» java.lang.Исключение IllegalMonitorStateException в java.lang.Object.notifyAll(собственный метод)
public class Buffer {
private StringBuilder text;
private final int MAX_PERMITS;
private ReentrantLock writerLock = new ReentrantLock();
private Semaphore semaphore;
public Buffer(int maxPermits) {
text = new StringBuilder();
MAX_PERMITS = maxPermits;
semaphore = new Semaphore(MAX_PERMITS);
}
public void write(String message) throws InterruptedException {
writerLock.lock();
System.out.println(ANSI_BLUE Thread.currentThread().getName() " has entered the critical section! Message: " message);
text.append(message); text.append(". ");
Thread.sleep(2000);
if(writerLock.isHeldByCurrentThread()) {
System.out.println(ANSI_BLUE "Lock held!");
writerLock.notifyAll();
}
writerLock.unlock();
}
public void read() throws InterruptedException{
if(text.length()==0) return;
writerLock.lock();
semaphore.acquire();
System.out.println(ANSI_GREEN Thread.currentThread().getName() " read the following message: " text.toString());
semaphore.release();
writerLock.unlock();
}
}
Ответ №1:
Явные блокировки, такие как ReentrantLock, по сути, являются отдельным типом блокировки для неявных «синхронизированных» блокировок. Другими словами, блокировка / разблокировка ReentrantLock — это отдельная схема для схемы synchronized / wait / notify. Поэтому вам нужно решить, какую схему вы хотите использовать:
- При явной блокировке вам нужно создать условие для блокировки (см. Метод Lock.NewCondition() ), затем использовать signal() и await() для условия.
- При неявной блокировке перед вызовом функции wait() / notify() вам необходимо выполнить синхронизацию с данным объектом, чтобы получить блокировку
Проблема с вашим кодом, по сути, заключается в том, что вы пытаетесь «смешивать и сопоставлять» между двумя схемами.
Преимущество явного условия заключается в том, что вы можете создавать разные условия и, следовательно, разъяснять в своем коде, какова фактическая причина (условие), по которой вы сигнализируете / ожидаете. Вы также можете решить, является ли блокировка «справедливой» или нет.
Недостатки неявной синхронизированной блокировки включают в себя:
- для каждого объекта есть только один из них, поэтому в вашем коде может быть менее ясно, почему вы на самом деле ожидаете / уведомляете;
- синхронизированные блокировки по сути являются «первым входом, первым выходом», поэтому потоки, которые захватывают блокировку, могут долгое время лишать другие потоки возможности ее получения.