Java 对锁定条件的同步调用出现非法监视器状态异常';s signalsall()
我有:Java 对锁定条件的同步调用出现非法监视器状态异常';s signalsall(),java,multithreading,locking,synchronized,Java,Multithreading,Locking,Synchronized,我有: static public final ReentrantLock lock = new ReentrantLock(); static public Condition my_condition = lock.newCondition(); 在myClass_1和myClass_2class I中调用: synchronized (myClass_1.my_condition){ myClass_1.my_condition.signalAll(); } 这给了我j
static public final ReentrantLock lock = new ReentrantLock();
static public Condition my_condition = lock.newCondition();
在myClass_1
和myClass_2
class I中调用:
synchronized (myClass_1.my_condition){
myClass_1.my_condition.signalAll();
}
这给了我
java.lang.IllegalMonitorStateException
。我已经在通过signal()
调用进行同步。是什么原因造成的?这是因为在发送信号之前,您没有获得可重入锁的锁
请阅读下面的重要声明
如果当任何条件等待或
如果调用了信令方法,则会生成非法MonitorStateException
扔
另外,请阅读下面的。现在,如果线程未获取锁,则不能调用wait()
,同样,如果未获取锁,则可以等待或发出信号条件
锁取代了同步方法和语句的使用,
条件取代了对象监视器方法的使用
底线:在等待或发出条件信号之前获取锁
lock.lock(); //Get the lock
while(/* whatever is your condition in myClass_1 and myClass_2 */){ //Or negative condition you want, but some code logic condition...
my_condition.await();
}
my_condition_2.signal(); //If you want to notify one thread. Like in case of Java's blocking queue, if you want to notify one thread to put or take.
my_condition_2.signalAll(); //If you want to notify all threads.
不要将同步
与锁一起使用。锁定和条件替换同步/等待/通知;它们不应与之结合使用
各国:
如果调用任何条件
等待或信令方法时未保持此锁,则会引发非法监视器状态异常
正确使用锁和条件如下所示:
lock.lock();
try {
someFlag = true;
condition.signalAll();
} finally {
lock.unlock();
}
以及其他地方:
lock.lock();
try {
someFlag = false;
while (!someFlag) {
condition.await();
}
} finally {
lock.unlock();
}
所有Condition.wait*方法都必须在while循环中调用,该循环检查条件所表示的数据,因为wait*方法会受到虚假唤醒的影响(就像Object.wait*方法一样)。我通过synchronized
实现所有权。但我刚刚将SignalAll更改为NotifyAll,不再出现错误。这是因为您使用了synchronized
关键字,这意味着对象的锁已被持有,因此调用NotifyAll
是有效的。根据您提供的代码,您使用了ReentrantLock
和Condition
来实现条件锁定,但现在它没有任何用处,因为您已经回到了对象的等待通知机制。我已经为您提供了由于ReentrantLock
锁定而产生的问题的正确解决方案。如果不来的错误不一定意味着它按要求运行,那么请验证您是否实现了所需的功能行为。我明白了。强制同步化(条件)的Lock()/Synchronize
机制是什么?原因从表面上看,条件
似乎独立于锁
工作,除了导致非法监视器状态异常
的耦合之外。使用同步
意味着要使用同步
方法和语句处理对象的锁ReentrantLock
类似于synchronized
方法和语句的扩展,可帮助您锁定和解锁一个方法之外的方法(synchronized
具有方法或块级别的范围,并且不会超出该范围,锁定到两个或多个方法)。因此,要锁定,可以使用synchronized
方法和语句,也可以使用ReentrantLock
。在您的例子中,您使用了ReentrantLock
和一个导出它的条件。这是我搜索到的一个很好的在线示例,看看-我明白了。这是有道理的。顺便问一下,对于signalall()
,是否有必要使用try{}finally{}
,因为在我的理解中,它不会抛出任何异常。将对unlock()的调用放在finally块中被认为是非常好的做法。这可能比冒险让锁永远保持不变要好。我理解,但这种做法不存在,因为try
块中存在抛出异常的例程吗?你想保证它无论如何都会被调用,而finally块就是实现这一点的方法。如果你问try catch finally是否和try finally一样好,答案是肯定的,它同样好。谢谢。我的意思是,如果没有异常,什么可能停止try块而不是finally块。如果它是一个外部的东西杀死了承载try-finally块的线程,那么它肯定也会停止finally块的执行吗?