странное поведение java.lang.Object.wait () - PullRequest
0 голосов
/ 24 сентября 2019

Почему здесь m.wait(); вызывает IllegalMonitorStateException исключение, даже если текущий поток ( main ) удерживает блокировку объекта m перед вызовом m.wait();?

import java.util.concurrent.locks.*;

class Lock1 extends ReentrantLock{
}

class Main{
public void test() throws InterruptedException{
synchronized(this){
Lock1 m = new Lock1();    
System.out.println("line 1");
m.lock();
System.out.println(m.getHoldCount());
System.out.println(m.isHeldByCurrentThread());
System.out.println("line 2");
m.wait();
System.out.println("line 3");
}
}
public static void main(String[] args) throws InterruptedException{
Main t1 = new Main();
t1.test();
}
}

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Вы смешиваете синхронизированный Object.wait () в старом стиле с методами ReentrantLock.

В частности, m.wait () - это oldstyle Object.wait (), а не что-либо определенное в ReentrantLock.Вам нужно использовать Условия ReentrantLock (т.е. newCondition ()), если вы хотите уступить, пока не произойдет изменение какого-либо условия, и другой поток не уведомит вас.

0 голосов
/ 24 сентября 2019

То, что вы заблокировали замок, не означает, что у вас есть монитор для указанного объекта.Вы должны использовать synchronized, чтобы взять монитор для объекта.Что-то вроде:

try
{
    synchronized(m)
    {
        m.wait();
    }
}
catch(InterruptedException e)
{
}

lock() для блокировки означает, что вы получаете блокировку, если она доступна.Если блокировка недоступна, поток будет блокироваться до тех пор, пока блокировка не будет снята другим потоком.
synchronized на объекте означает получение монитора для указанного объекта.Если монитор недоступен, поток будет блокироваться до тех пор, пока монитор не будет освобожден другим потоком, и текущий поток не будет notify() настроен на пробуждение.

...