2017-11-21 3 views
2

나는 오라클 웹 사이트의 자바 튜토리얼을 따라 Threads를 배우고있다.java.lang.IllegalMonitorStateException on notifyAll() method

wait() 및 notifyAll()과 관련하여 몇 가지 코드를 작성했습니다. 내 기대 출력 run() 10 번 메시지를 인쇄하고 실행 메서드에서 '기쁨'false로 설정할 때 guardedJoy(GuardedBlock guardedBlock) 메서드에서 "StopFun 스레드에 의해 중지 된"메시지를 인쇄하십시오.

이것은 내 코드입니다.

public class GuardedBlock { 

private boolean joy = true; 

public synchronized void guardedJoy(GuardedBlock guardedBlock) { 

    System.out.println(Thread.currentThread().getName() + " Guard Joy method started"); 
    while (guardedBlock.joy) { 
     try { 
      System.out.println(Thread.currentThread().getName() + " Going to waiting state"); 
      guardedBlock.wait(); 
     } catch (InterruptedException ex) { 
     } 
    } 
    System.out.println("Fun stopped by StopFun Thread"); 
} 

private static class StopFun implements Runnable { 

    private GuardedBlock guardedBlock; 

    public StopFun(GuardedBlock guardedBlock) { 
     this.guardedBlock = guardedBlock; 
    } 

    @Override 
    public void run() { 

     for (int x = 0; x < 100; x++) { 
      try { 
       Thread.sleep(500); 
       System.out.println("Allowing fun since its only " + x + " times - " + Thread.currentThread().getName()); 

       if (x == 10) { 
        guardedBlock.joy = false; 
        guardedBlock.notifyAll(); 
        break; 
       } 
      } catch (InterruptedException ex) { 
      } 
     } 
    } 
} 

public static void main(String[] args) { 

    GuardedBlock guardedBlock = new GuardedBlock(); 

    StopFun sf = new StopFun(guardedBlock); 
    Thread stopFun = new Thread(sf); 
    stopFun.start(); 

    guardedBlock.guardedJoy(guardedBlock); 
    } 
} 

run 메소드의 코드는 정상적으로 실행되지만 이후에는 이와 같은 예외가 발생합니다.

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Synchronization.GuardedBlock$StopFun.run(GuardedBlock.java:38) 
    at java.lang.Thread.run(Thread.java:748) 

나는 thisthis 같은 사이트의 질문과 답변의 몇 겪었지만 정확히 내가 뭘 잘못 알아낼 수 없었다. 도움은 많은 가치가 있습니다.

감사합니다.

+0

[문서] (https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#notifyAll--)는 친구입니다. "** 오류 : ** IllegalMonitorStateException - 현재 스레드가이 객체의 모니터 소유자가 아닌 경우 " – VGR

답변

3

wait()notify()/notifyAll()synchronized 블록으로 호출되어야합니다.

synchronized (guardedBlock) { 
    guardedBlock.notifyAll(); 
} 

등등.

+0

답변 해 주셔서 감사합니다. though.wait()가 이미 동기화 된 메서드에 있습니다. 그렇다면 별도의 동기화 된 블록을 도입해야합니까? –

+0

죄송합니다.이 메서드가 동기화되지 않았습니다. 그러나'this'에 동기화되어'guardedBlock'에'wait()'가 호출됩니다. 프로그램에서'guardedBlock'은'guardedBlock.guardedJoy (guardedBlock);'호출로'this '를 호출하고,'synchronized' 블록을 추가하지 않아도 작동합니다. 그러나 이것은 약간 깨지기 쉽습니다 . 물론'notifyAll()'도 반드시 동기화되어야합니다. –

+0

synchronized 블록에서도'guardedBlock.joy = false; '를 사용하는 것이 좋습니다. –

관련 문제