Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 对锁定条件的同步调用出现非法监视器状态异常';s signalsall()_Java_Multithreading_Locking_Synchronized - Fatal编程技术网

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块的执行吗?