2016-11-21 1 views
0

교수가 제공 한 책의 시험을 치고 있으며 스레드 및 동기화와 관련된 코드가 있습니다. 상태가 변경 될 때마다 알림을 받고 싶습니다. 상태 변경을 놓치지 않고).notify 및 notifyAll/synchronising 코드 (이해 도움말)

public class C { 

    private int state = 0; // the state 
    private boolean modified = false; // to show if the state was changed since actualization 

    public synchronized void printNewState() { 
     while (true) { 
      if (!modified) { 
       wait(); 
      } 
      System.out.println(state); 
      modified = false; 
      notify(); 
     } 
    } 

    public synchronized void setValue(int v) { 
     if (modified) { 
      wait(); 
     } 
     state = v; 
     notify(); 
     modified = true; 
     System.out.println("value set"); 
    } 
} 

그리고이 다음은 writen 것 :
을하지만, (INT)가 printNewState 스레드를 깰 방법의 SetValue는()에서 통지가 보장되지 않습니다! 자바에서 우리가가는 notifyAll (의 도움으로이 문제 를 해결) 조금 바쁜 대기 걸릴 다음 통지 이유) (도가는 notifyAll로 변경되지 않았습니다

public synchronized void printNewState() { 
    while (true) { 
     while (!modified) { 
      wait(); 
     } 
     System.out.println(state); 
     modified = false; 
     **notify();** \\(?) 
    } 
} 

public synchronized void setValue(int v) { 
    while (modified) { 
     wait(); 
    } 
    state = v; 
    notifyAll(); 
    modified = true; 
    System.out.println("value set"); 
} 

이해가 안가? 이 통지가 setValue (int)의 thread에 보내지는 것이 보증되지 않는 경우가 있습니다. ???

notifyAll() 방법은 모든 대기 스레드를 깨어 반면 notify() 방법은, 하나의 대기 스레드를 깨어 나면 당신

답변

0

감사드립니다. 문제는 notify()을 사용하면 깨우쳐 진 스레드가 효과적으로 무작위가된다는 것입니다.

다른 스레드가 실수로 또는 악의적으로 같은 개체에있는 경우 깨우려고하는 스레드 대신 알림을받을 수 있습니다.

자세한 내용은 this answer을 참조하십시오. 그 대답에 대한 의견도 꽤 흥미 롭습니다. 그것은 의미가 업데이트를 게시 할 스레드를 대기 모든 통지하지 않도록

당신이 게시 코드 샘플, 편집

printNewState() 내 첫 notify()은 한 번에 하나의 업데이트를 처리 할 수 ​​있습니다 . 그러나 코드에서는 setValue(int)을 호출하는 스레드 만 기다리고 있다고 가정합니다.

public synchronized void setValue(int)은 본질적으로 방법의 첫 번째 줄에 synchronized(this)을 갖는 것과 동일하므로 실제로 보장되지 않습니다. C 클래스의 인스턴스에 대한 참조가있는 코드는 코드를 기다리고 코드를 망칠 수 있습니다.

동기화 및 대기/알림 작업은 개체 잠금/모니터에서 수행되어야합니다. private final Object monitor = new Object(), synchronized(this.monitor), this.monitor.wait(), this.monitor.notifyAll()

나는 또한 modified = true 요구 setValue(int)에서 notifyAll() 전에 배치 할 수 있습니다 싶습니다, 그렇지 않으면 다른 기다리고 업데이트 스레드 업데이트를 몰래 printNewState()없이 진행됩니다.

또한 private boolean modified은 실제로 private volatile boolean modified이어야하며 private int state과 동일하지만 AtomicInteger가 더 좋은 옵션 일 수 있습니다.

+0

안녕하세요. Grexis, 제가 질문을 편집했습니다. 죄송합니다. 나는 너의 대답 tho에 흥미있다. – ovoxo

+0

@ovoxo, 제 편집 참조. tl; dr은'notifyAll()'대신'notify()'를 쓰는 것이 스레드 업데이트 만 기다리고있는 한 의미가 있습니다. – Grexis

+0

답변 해 주셔서 대단히 감사합니다. :) – ovoxo