2016-10-29 2 views
0

내가 두 스레드가 서로 뭔가를 인쇄 할 수 있도록 노력 java.lang.IllegalMonitorStateException`,하지만 난 얻을 결과였다 : 이미 동기화 된 블록의 공유 객체를 포함하고 호출 한 자바 멀티 스레드 오류가`

0 
Exception in thread "Thread-0" wait in decrement 
java.lang.IllegalMonitorStateException 
    at java.lang.Object.notify(Native Method) 
    at thread.Multithread2.increment(Multithread2.java:38) 
    at thread.Multithread2.run(Multithread2.java:18) 
    at java.lang.Thread.run(Unknown Source) 

이 객체의 wait()/notify(). 나는 왜 아직도 예외를 던지는 지 모르겠다.

public class Multithread2 implements Runnable { 

    private Integer integer; 
    private int method; 

    public Multithread2(Integer integer, int method) { 
     this.integer = integer; 
     this.method = method; 
    } 

    @Override 
    public void run() { 
     try { 
      Thread.sleep(20); 
      for(int i = 0; i < 5; i++) { 
       if(method == 1) { 
        increment(); 
       } else { 
        decrement(); 
       } 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void increment() throws InterruptedException { 
     synchronized(integer) { 
      while(integer > 0) { 
       integer.wait(); 
      } 
      System.out.println(integer); 
      integer++; 
      integer.notify(); 
     } 
    } 

    public void decrement() throws InterruptedException { 
     synchronized(integer) { 
      while(integer <= 0) { 
       integer.wait(); 
      } 
      System.out.println("decrement: " + integer); 
      integer--; 
      integer.notify(); 
     } 
    } 
} 

주요 방법 :

Integer integer = new Integer(0); 
Thread t1 = new Thread(new Multithread2(integer, 1)); 
t1.start(); 
Thread t2 = new Thread(new Multithread2(integer, 2)); 
t2.start(); 
+1

'정수 ++ '는'정수 = 정수 +1 '과 같습니다. 'synchronized '와 동일한'integer'에 대해'notify() '를 호출하지 않습니다. –

답변

2
integer++ 

integer = Integer.valueOf(integer.getValue() + 1); 

그래서 그것은 다른 정수 인스턴스와 정수 변수를 초기화하는 것과 같다. 정수는 변경 불가능하므로 상태를 변경할 수 없습니다. 이 새 Integer 인스턴스에서 notify()를 호출하고이 새 인스턴스에서 잠금을 획득하지 않았으므로 예외가 발생합니다.

변경할 수있는 스레드로부터 안전한 카운터 클래스를 사용하십시오. 공유되고 불변 인 Integer 인스턴스를 동기화하는 것은 끔찍한 생각입니다. 좋은 경험 법칙은 동기화하는 필드를 final으로 만드는 것입니다. 그렇게하면 컴파일 오류가 발생하고 컴파일 오류는이 상황에서 친구가됩니다. 단, 실제로 무엇을 말하는지주의해야합니다.

+0

아니면 그냥 AtomicInteger라고 생각합니다. –

+0

네, 그걸 사용할 수도 있습니다. –

+0

"그렇게하면 컴파일 오류가 발생합니다." ... 컴파일 오류는이 상황에서 당신의 친구입니다. 실제로 당신에게 말하는 내용에주의를 기울이면됩니다. –