IT

wait () 호출시 IllegalMonitorStateException

lottoking 2020. 6. 7. 10:08
반응형

wait () 호출시 IllegalMonitorStateException


내 프로그램에 Java에서 멀티 스레딩을 사용하고 있습니다. 스레드를 성공적으로 실행했지만 사용할 때 Thread.wait()던지고 java.lang.IllegalMonitorStateException있습니다. 스레드가 알림을받을 때까지 기다리려면 어떻게해야합니까?


당신이 synchronized하기 위해서는 블록에 있어야 Object.wait()합니다.

또한 구식 스레딩 패키지 대신 동시성 패키지를 보는 것이 좋습니다. 더 안전하고 작업하기 쉽습니다 .

행복한 코딩.

편집하다

Object.wait()객체 잠금을 유지하지 않고 액세스하려고 할 때 예외가 발생 한다는 것을 의미한다고 가정했습니다 .


wait에 정의되어 Object있지만 아닙니다 Thread. 모니터 Thread가 약간 예측할 수 없습니다.

모든 Java 객체에는 모니터가 있지만 일반적으로 전용 잠금 장치를 사용하는 것이 좋습니다.

private final Object lock = new Object();

명명 된 클래스를 사용하면 적은 메모리 비용 (프로세스 당 약 2K)으로 진단을보다 쉽게 ​​읽을 수 있습니다.

private static final class Lock { }
private final Object lock = new Lock();

하기 위해 wait또는 notify/ notifyAll객체, 당신은 함께 잠금 유지 될 필요가 synchronized문을. 또한 while깨우기 상태를 확인하기 위해 루프 가 필요합니다 (이유를 설명하기 위해 스레드에서 좋은 텍스트를 찾으십시오).

synchronized (lock) {
    while (!isWakeupNeeded()) {
        lock.wait();
    }
}

알리기 위해:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}

멀티 스레딩에 들어갈 때 Java 언어와 java.util.concurrent.locks잠금 (및 java.util.concurrent.atomic)을 모두 이해하는 것이 좋습니다. 그러나 가능하면 java.util.concurrent데이터 구조를 사용하십시오 .


나는이 스레드가 거의 2 세라는 것을 알고 있지만 동일한 문제 로이 Q / A 세션에 왔기 때문에 여전히이를 닫아야합니다 ...

이 illegalMonitorException 정의를 반복해서 읽으십시오.

IllegalMonitorException은 스레드가 객체의 모니터를 기다리려고 시도했거나 지정된 모니터를 소유하지 않고 객체의 모니터를 기다리는 다른 스레드에 알리려고 시도했음을 나타냅니다.

이 줄은 두 가지 상황 중 하나가 발생할 때 IllegalMonitorException이 계속 발생한다고 말합니다.

1> 지정된 모니터를 소유하지 않고 객체의 모니터를 기다립니다.

2> 지정된 모니터를 소유하지 않고 객체의 모니터를 기다리는 다른 스레드에 알립니다.

어떤 사람들은 대답을 얻었을 수도 있습니다 ... 모두 그렇지 않은 사람은 2 명을 확인하십시오 ....

동기화 (개체)

object.wait ()

객체 가 동일한 경우 에는 illegalMonitorException이 발생하지 않습니다.

이제 IllegalMonitorException 정의를 다시 읽으면 다시 잊어 버리지 않습니다.


귀하의 의견을 바탕으로 다음과 같은 일을하는 것처럼 들립니다.

Thread thread = new Thread(new Runnable(){
    public void run() { // do stuff }});

thread.start();
...
thread.wait();

세 가지 문제가 있습니다.

  1. 다른 사람들이 말했듯 obj.wait()이 현재 스레드가 기본 잠금 / 뮤텍스를 보유하고있는 경우에만 호출 할 수 있습니다 obj. 현재 스레드가 잠금을 보유하지 않으면 현재보고있는 예외가 발생합니다.

  2. thread.wait()전화는 당신이 그것을 할 것으로 예상 것으로 보인다 무엇을하지 않습니다. 특히 지정된 스레드가 대기 thread.wait() 하지 않습니다 . 오히려 원인 현재 스레드가 다른 스레드를 호출 할 때까지 기다려야 thread.notify()또는 thread.notifyAll().

    There is actually no safe way to force a Thread instance to pause if it doesn't want to. (The nearest that Java has to this is the deprecated Thread.suspend() method, but that method is inherently unsafe, as is explained in the Javadoc.)

    If you want the newly started Thread to pause, the best way to do it is to create a CountdownLatch instance and have the thread call await() on the latch to pause itself. The main thread would then call countDown() on the latch to let the paused thread continue.

  3. Orthogonal to the previous points, using a Thread object as a lock / mutex may cause problems. For example, the javadoc for Thread::join says:

    This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.


Since you haven't posted code, we're kind of working in the dark. What are the details of the exception?

Are you calling Thread.wait() from within the thread, or outside it?

I ask this because according to the javadoc for IllegalMonitorStateException, it is:

Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

To clarify this answer, this call to wait on a thread also throws IllegalMonitorStateException, despite being called from within a synchronized block:


     private static final class Lock { }
     private final Object lock = new Lock();

    @Test
    public void testRun() {
        ThreadWorker worker = new ThreadWorker();
        System.out.println ("Starting worker");
        worker.start();
        System.out.println ("Worker started - telling it to wait");
        try {
            synchronized (lock) {
                worker.wait();
            }
        } catch (InterruptedException e1) {
            String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
            System.out.println (msg);
            e1.printStackTrace();
            System.out.flush();
        }
        System.out.println ("Worker done waiting, we're now waiting for it by joining");
        try {
            worker.join();
        } catch (InterruptedException ex) { }

    }

In order to deal with the IllegalMonitorStateException, you must verify that all invocations of the wait, notify and notifyAll methods are taking place only when the calling thread owns the appropriate monitor. The most simple solution is to enclose these calls inside synchronized blocks. The synchronization object that shall be invoked in the synchronized statement is the one whose monitor must be acquired.

Here is the simple example for to understand the concept of monitor

public class SimpleMonitorState {

    public static void main(String args[]) throws InterruptedException {

        SimpleMonitorState t = new SimpleMonitorState();
        SimpleRunnable m = new SimpleRunnable(t);
        Thread t1 = new Thread(m);
        t1.start();
        t.call();

    }

    public void call() throws InterruptedException {
        synchronized (this) {
            wait();
            System.out.println("Single by Threads ");
        }
    }

}

class SimpleRunnable implements Runnable {

    SimpleMonitorState t;

    SimpleRunnable(SimpleMonitorState t) {
        this.t = t;
    }

    @Override
    public void run() {

        try {
            // Sleep
            Thread.sleep(10000);
            synchronized (this.t) {
                this.t.notify();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Thread.wait() call make sense inside a code that synchronizes on Thread.class object. I don't think it's what you meant.
You ask

How can I make a thread wait until it will be notified?

You can make only your current thread wait. Any other thread can be only gently asked to wait, if it agree.
If you want to wait for some condition, you need a lock object - Thread.class object is a very bad choice - it is a singleton AFAIK so synchronizing on it (except for Thread static methods) is dangerous.
Details for synchronization and waiting are already explained by Tom Hawtin. java.lang.IllegalMonitorStateException means you are trying to wait on object on which you are not synchronized - it's illegal to do so.


Not sure if this will help somebody else out or not but this was the key part to fix my problem in user "Tom Hawtin - tacklin"'s answer above:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}

Just the fact that the "lock" is passed as an argument in synchronized() and it is also used in "lock".notifyAll();

Once I made it in those 2 places I got it working


I received a IllegalMonitorStateException while trying to wake up a thread in / from a different class / thread. In java 8 you can use the lock features of the new Concurrency API instead of synchronized functions.

I was already storing objects for asynchronous websocket transactions in a WeakHashMap. The solution in my case was to also store a lock object in a ConcurrentHashMap for synchronous replies. Note the condition.await (not .wait).

To handle the multi threading I used a Executors.newCachedThreadPool() to create a thread pool.


Those who are using Java 7.0 or below version can refer the code which I used here and it works.

public class WaitTest {

    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    public void waitHere(long waitTime) {
        System.out.println("wait started...");
        lock.lock();
        try {
            condition.await(waitTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        lock.unlock();
        System.out.println("wait ends here...");
    }

    public static void main(String[] args) {
        //Your Code
        new WaitTest().waitHere(10);
        //Your Code
    }

}

참고URL : https://stackoverflow.com/questions/1537116/illegalmonitorstateexception-on-wait-call

반응형