2011-12-26 6 views
0
import java.util.*; 
import java.io.*; 
import java.util.regex.*; 

class ZiggyTest2 extends Thread{ 

    String sa; 

    public ZiggyTest2(String sa){ 
     this.sa = sa; 
    } 

    public void run(){ 
     synchronized(sa){ 
      while(!sa.equals("Done")){ 
       try{ 
        sa.wait(); 
       }catch(InterruptedException is){System.out.println("IE Exception");} 
      } 
     } 

     System.out.println(sa); 
    } 
} 

class Test{ 
    private static String sa = new String("Not Done"); 

    public static void main(String[] args){ 
     Thread t1 = new ZiggyTest2(sa); 
     t1.start(); 

     synchronized(sa){ 
      sa = new String("Done"); 
      sa.notify(); 
     } 
    } 
} 

나는 다음과 같은 예외가 위의 프로그램을 실행하면 :스레드 동시성 - 동기화 및 잠금.

Exception in thread "main" java.lang.IllegalMonitorStateException 
     at java.lang.Object.notify(Native Method) 
     at Test.main(ZiggyTest2.java:35) 

몇 가지 질문 :

  • 왜 예외 : IllegalMonitorStateException? Test.sa는 새로운 String 객체에 할당되었으므로 saigger()가 ZiggyTest2에서 사용 된 잠금과 다른 잠금에서 호출되기 때문에 ZiggyTest2 스레드가 무한정 대기 할 것으로 예상했습니다.

  • 위 예제에서 wait() & notify()가 "sa"개체에서 호출되었습니다. notify()를 호출하고 notify()/wait()를 호출하는 것, 즉 sa.wait() 및 sa.notify()를 사용하는 것의 차이점은 무엇입니까?

  • 테스트 클래스에서 동기화 된 블록은 sa 객체에 대한 잠금을 가지며 sa 객체는 정적이지만 ZiggyTest2 클래스에서 동기화 된 블록은 동일한 sa 객체 참조를 사용하지만 비 정적 참조 ? 하나는 정적이고 다른 하나는 그렇지 않다는 것을 감안할 때, 둘 다 여전히 동일한 잠금을 사용합니까?

답변

2

당신이 sa하여 문자열 참조의 내용을 변경하지 않는

sa = new String("Done"); 

을 실행합니다. sa에 새 String 인스턴스 (새 객체)를 지정합니다. 문자열은 변경할 수 없습니다. 그들의 가치를 바꾸는 것은 불가능합니다.

이것은 sa (첫 번째 객체 : "완료되지 않음")에서 동기화 한 다음 sa (두 번째 객체 : 완료)에 새 객체를 할당하고 두 번째 객체에서 알림을 호출 함을 의미합니다. 두 번째 객체에서 동기화하지 않았으므로 첫 번째 객체에서 동기화되었으므로 IllegalMonitorException이 발생합니다. 객체에 대한 고유 알림을 소유 한 경우에만 객체에 대한 알림을 호출 할 수 있습니다. 그래서 자물쇠가 항상 최종이어야합니다.

notify() 호출은 this.notify()를 호출하는 것과 같습니다. 따라서 this.notify()sa.notify()은 두 개의 서로 다른 객체에서 notify()을 호출 중입니다. 첫 번째 스레드는 this에서 대기중인 스레드에 알리고 두 번째 스레드는 sa에서 대기중인 스레드에 알립니다.

변수가 정적이거나 고정되어 있지 않다는 사실은 중요하지 않습니다. 잠금은 참조가 아닌 오브젝트와 연관됩니다.

+0

감사합니다. @JB. 훌륭한 설명. – ziggy

+0

그러나 주 기능의 동기화 된 블록에서 완전히 새로운 문자열 참조 (전혀 _sa_를 사용하지 않음)를 사용하더라도 여전히 오류가 발생합니다! – Santosh

+0

무엇을 의미합니까? 나는 당신이 객체에 대한 통지를 호출하기 위해 객체 모니터를 소유해야한다고 설명했다. someObject.notify()를 호출하면 synchronized (someObject)를 호출해야합니다 (물론 잠금을 해제하지 않았 음) –