即使线程持有 ReentrantLock 对象,也会发生 IllegalMonitorStateException
IllegalMonitorStateException occurs even when the thread holds the ReentrantLock object
即使Writer线程持有锁,当下面代码为运行时会出现以下异常。
作者进入临界区!信息:在你的痛苦中保持坚强
锁定!
java.lang.Object.notifyAll(本机方法)
线程“Writer”java.lang.IllegalMonitorStateException 中的异常
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();
}
}
ReentrantLock 等显式锁本质上是对隐式 'synchronised' 锁的一种独立类型的锁定。换句话说,locking/unlocking ReentrantLock 是 synchronized/wait/notify 方案的独立方案。所以你需要决定你想使用哪种方案:
- 使用显式锁,需要在锁上创建条件(参见Lock.newCondition()方法),然后在条件上使用signal()和await()。
- 使用隐式锁,在调用 wait()/notify() 之前,您需要在相关对象上同步以获得锁
您的代码存在的问题本质上是您试图在两种方案之间“混合搭配”。
显式条件的优点是您可以创建不同的条件,因此可以在您的代码中明确说明您 signalling/waiting 的实际原因(条件)是什么。您还可以决定是否锁定'fair'。
隐式同步锁的缺点包括:
- 每个对象只有一个,因此在您的代码中可能不太清楚 为什么 您实际上是 waiting/notifying;
- 同步锁本质上是“先进先出”的,因此占用锁的线程可能会使其他线程长时间无法获得锁。
即使Writer线程持有锁,当下面代码为运行时会出现以下异常。
作者进入临界区!信息:在你的痛苦中保持坚强 锁定! java.lang.Object.notifyAll(本机方法)
线程“Writer”java.lang.IllegalMonitorStateException 中的异常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();
}
}
ReentrantLock 等显式锁本质上是对隐式 'synchronised' 锁的一种独立类型的锁定。换句话说,locking/unlocking ReentrantLock 是 synchronized/wait/notify 方案的独立方案。所以你需要决定你想使用哪种方案:
- 使用显式锁,需要在锁上创建条件(参见Lock.newCondition()方法),然后在条件上使用signal()和await()。
- 使用隐式锁,在调用 wait()/notify() 之前,您需要在相关对象上同步以获得锁
您的代码存在的问题本质上是您试图在两种方案之间“混合搭配”。
显式条件的优点是您可以创建不同的条件,因此可以在您的代码中明确说明您 signalling/waiting 的实际原因(条件)是什么。您还可以决定是否锁定'fair'。
隐式同步锁的缺点包括:
- 每个对象只有一个,因此在您的代码中可能不太清楚 为什么 您实际上是 waiting/notifying;
- 同步锁本质上是“先进先出”的,因此占用锁的线程可能会使其他线程长时间无法获得锁。