2012-03-28 5 views
1

모니터 개체?자바는 내가 읽었

나는 이것을 내 코드에서 시도해도 작동하지 않는다.

private Object data; 
    private Object sync = new Object(); 

    public static void main(String[] args) { 
     SimpleProducerConsumer pc = new SimpleProducerConsumer(); 
     new Thread(pc.new Producer()).start(); 
     new Thread(pc.new Consumer()).start(); 
    } 

    public Object pop() { 
     try { 
      sync.wait(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     System.out.println("Before"); 
     Object d = data; 
     data = null; 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("pop"); 
     System.out.println("After"); 
     sync.notify(); 
     return d; 
    } 

    public void push(Object d) { 
     try { 
      sync.wait(); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     try { 
      Thread.sleep(10); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     data = d; 
     System.out.println("push"); 
     sync.notify(); 
    } 

    class Producer implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       push(new Object()); 
      } 
     } 
    } 

    class Consumer implements Runnable { 
     @Override 
     public void run() { 
      while (true) { 
       pop(); 
      } 
     } 
    } 

내 코드가 잘못되었습니다.

답변

3

아니요, sync.wait()sync.notify()sychronize (sync) { ...... }과 동의어가 아닙니다.

실제로 wait으로 전화 하시려면 이 있고 synchronized 블록에 있어야합니다.

synchronize, waitnotify의 개념을 설명하고 차이점은 명확해질 것입니다.

  • 스레드가 (잠금이 수행되도록하고 다른 스레드는 그 시점에서의 블록을 입력 할 수 없음을 의미한다)을 sync 모니터 잠금 잡고 synchronized (sync) { ... } 블록 들어간다.

  • 스레드가 sync.wait()을 호출하면 sync의 잠금이 일시적으로 해제됩니다. (그것은 일이 뭔가을 기다리고있다. 일 할 수 있도록 잠금이 필요합니다 뭔가.)

  • 이 스레드는 sync.notify()에 어떤 시점에서 그들이 실행을 다시 시작을 일어난 뭔가 다른 스레드에 통보 호출 .

내 코드에 어떤 문제가 있습니까? 내가 예를 들어 당신이 가정

두 개의 스레드가 뭔가를 팝업하려고하면 그들이 무엇을 피해야 있는지 확인하려면 다음

Thread 1    Thread 2 
-------------------------------------- 
Object d = data; 
         Object d = data; 
         data = null; 
data = null; 
return d; 
         return d; 

가 확실 d = datadata = null 있는지 확인해야이 문제를 방지하려면 원자 번호가 인 경우이 발생합니다.

이는

Object d; 
synchronized (sync) { 
    d = data; 
    data = null; 
} 

을 수행하여 달성 할 수있다 (이제 위의 스레드 (1)의 제 1 및 제 2 문은 분할 할 수 없습니다.)

은 또한 당신이 pop 차단해야 할 것 같다, 예를 들어 d == null이라면 다른 스레드가 push이 될 때까지 기다려야합니다.

synchronized (sync) { 
    while (d == null) 
     sync.wait(); 
} 

을 수행하여 달성 (푸시 방법으로 원자 적으로 수행 될 필요가있는 모든 피복 synchronized 블록 내에 다시) sync.notify()push에서 수행 될 수있다.

관련 질문/더 읽기 :

1

당신은 notify()에 대해 동일한 잠금 개체를 기다리고 모두 당신의 push()pop() 방법을 가지고 있지만, 그 객체에 notify() 또는 notifyAll()를 호출 아무도 없다, 그래서 그들은 무한정 기다리고 있습니다. 여기에 어떻게됩니까 은 다음과 같습니다

  1. push() 내부 sync.wait() 통화 생산자 기다리는 사람이 전화하는 사람이 pop() 내부의 sync.wait() 통화 sync.notify()
  2. 소비자 대기와 통화 할 수 sync.notify()
  3. 교착 상태
1

아니요, 완전히 다릅니다. 어떤 조건이 충족 될 때까지 실행을 일시 중지하려는 경우 wait()synchronized 블록 내부에서 호출합니다. 동일한 개체 (예 : synchronized 블록)에 notify() 또는 notifyAll()을 사용하면 해당 조건이 충족됩니다.

따라서이 상황에서 두 스레드는 실제로 같은 개체의 블록 synchronized에있을 수 있습니다. 이 중 하나가 wait() 일 때 허용됩니다. 두 번째 스레드가 notify()을 호출 한 블록 synchronized을 종료하면 첫 번째 스레드가 다시 시작됩니다.