Java 使用RentrantLock实现生产者-消费者时发生IllegalMonitorStateException
我试图在java中使用ReentrantLock实现生产者消费者Java 使用RentrantLock实现生产者-消费者时发生IllegalMonitorStateException,java,multithreading,Java,Multithreading,我试图在java中使用ReentrantLock实现生产者消费者 Condition producerlock = lock.newCondition(); Condition consumerlock = lock.newCondition(); 它有两个条件,一个是生产者,另一个是消费者 这里我们有一个处理器类,它有两个方法生产者消费者和一个堆栈 Stack<Integer> hellostrack = new Stack<>(); p
Condition producerlock = lock.newCondition();
Condition consumerlock = lock.newCondition();
它有两个条件,一个是生产者,另一个是消费者
这里我们有一个处理器类,它有两个方法生产者消费者和一个堆栈
Stack<Integer> hellostrack = new Stack<>();
public void produce() throws InterruptedException {
lock.tryLock();
System.out.println("inside producer method");
while (true) {
try {
if (hellostrack.size() > 8) {
System.out.println("stack is full its time for me to go to sleep");
producerlock.await();
}
System.out.println("thread is alive and kicking");
hellostrack.add(new Random().nextInt());
consumerlock.signalAll();
} finally {
System.out.println("Exception occours in producer Thread");
lock.unlock();
}
}
}
public void consume() throws InterruptedException{
System.out.println("inside consumer method");
lock.tryLock();
try {
while (true) {
if (hellostrack.isEmpty()) {
System.out.println("stack is empty im going to sleep");
consumerlock.await();
} else {
System.out.println("poping elelmts from stock" + hellostrack.pop());
consumerlock.signalAll();
}
} }finally {
System.out.println("Exception occours at consumer");
lock.unlock();
}
}
请注意,您处于
while(true)
循环中。您永远不会离开循环,这意味着您将解锁,然后再也不会重新锁定。在第一个循环之后,您将再次尝试解锁,但由于您不拥有该锁,因此将引发异常
将
tryLock
移动到while(true)
下,可能会工作得更好。请注意,您处于while(true)
循环中。您永远不会离开循环,这意味着您将解锁,然后再也不会重新锁定。在第一个循环之后,您将再次尝试解锁,但由于您不拥有该锁,因此将引发异常
将tryLock
移动到while(true)
下,可能会工作得更好。此外,您的代码还有一些其他问题
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
此用法可确保在获得锁时将其解锁,而在未获得锁时不会尝试解锁
您的代码不会检查tryLock
的结果,这意味着线程有可能在不持有锁的情况下移动到受保护的代码中。这意味着除了不正确同步的访问之外,还有可能在不持有锁的情况下调用wait()
、signalAll()
、和unlock()
在这种情况下,您要调用的方法是:
获得锁
如果锁不可用,则出于线程调度目的,当前线程将被禁用,并处于休眠状态,直到获得锁为止
这意味着线程将等待获得锁后再继续。但是,由于您的方法已经抛出了InterruptedException
,因此您最好使用。这与lock()
基本相同,但等待可能会被中断consumerlock.signalAll()
方法中的consumer()
一旦您消费了一个元素,您就要通知生产者有更多的可用空间。您应该调用producerlock.signalAll()
await()
在检查条件的循环中调用await()
是一种很好的做法。原因是线程可以出于任何原因(很少)唤醒。如果发生这种情况,并且存在循环,线程将重新检查条件,如果合适,将再次调用await()
此外,您正在使用signalAll()
。该方法通知所有等待的线程唤醒,尝试获取锁,然后继续。由于不使用循环,所有唤醒的线程都将继续执行可能导致不一致/不正确状态的任何修改。相反,拥有循环意味着如果其中一个唤醒的线程导致等待条件再次为真,则任何后续线程都将返回等待状态
使用循环类似于:
while (hellostrack.size() > 8) { // should this be >= 8?
producerlock.await();
}
// and
while (hellostrack.isEmpty()) {
consumerlock.await();
}
Lock lock = ...;
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
此用法可确保在获得锁时将其解锁,而在未获得锁时不会尝试解锁
您的代码不会检查tryLock
的结果,这意味着线程有可能在不持有锁的情况下移动到受保护的代码中。这意味着除了不正确同步的访问之外,还有可能在不持有锁的情况下调用wait()
、signalAll()
、和unlock()
在这种情况下,您要调用的方法是:
获得锁
如果锁不可用,则出于线程调度目的,当前线程将被禁用,并处于休眠状态,直到获得锁为止
这意味着线程将等待获得锁后再继续。但是,由于您的方法已经抛出了InterruptedException
,因此您最好使用。这与lock()
基本相同,但等待可能会被中断consumerlock.signalAll()
方法中的consumer()
一旦您消费了一个元素,您就要通知生产者有更多的可用空间。您应该调用producerlock.signalAll()
await()
在检查条件的循环中调用await()
是一种很好的做法。原因是线程可以出于任何原因(很少)唤醒。如果发生这种情况,并且存在循环,线程将重新检查条件,如果合适,将再次调用await()
此外,您正在使用signalAll()
。该方法通知所有等待的线程唤醒,尝试获取锁,然后继续。由于不使用循环,所有唤醒的线程都将继续执行可能导致不一致/不正确状态的任何修改。相反,拥有循环意味着