JAVA Thread wait, notify, notifyAll 쓰레드 협조

JAVA Thread wait, notify, notifyAll 쓰레드 협조


우선 wait()메소드는 lock을 소유한 Thread가 자신의 제어권을 양보하고WAITING 또는 TIMED_WAITING상태에서 대기하기 위해서 사용된다. 반대로 notify()와 notifyAll()은 wait상태에 빠져있는 다른 Thread를 다시 RUNNABLE상태로 변경시키는 역할을 한다. 한가지 착각하기 쉽지만 반드시 유의해야 하는 점은 wait, notify, notifyAll은 Thread의 메소드가 아니라 Object의 메소드라는 점이다.


wait()

Lock을 소유한 Thread가 obj.wait()를 수행하는 경우 현재 Thread는 일시정지 되고 obj의 wait set(가상의 개념)으로 들어가게 된다. Thread가 obj내부에서 wait하고 있다고 생각하면 이해가 쉽다. wait()를 실행하기 위해서는 Thread가 lock을 소유하고 있어야 하고 wait가 수행되면 lock이 자동으로 해제되어 다른 Thread가 접근할수 있게 된다.

  • lock을 소유한 Thread가 lock이 된 obj에 대하여 호출
  • Thread는 lock을 반납하고 obj내부에서 WAITING 혹은 TIMED WAITING상태로 대기l
  • lock이 해제되었기 때문에 obj에 대해서 다른 Thread가 접근 가능


일반적인 synchronized의 상황이다. Thread A는 어떤 인스턴스의 lock을 획득하고 synchronized 메소드 블럭에서 wait();를 수행하기 직전인 상황이다. Thread B는 lock에 의해서 인스턴스에 접근을 blocking당하고 있다.  




이때, Thread A가 wait();를 수행하게 되면 Thread A는 WAIT SET(쓰레드 대기실)에서 WAITING, TIMED_WAITING상태로 대기하게 된다. WAIT SET에 들어가는 경우 Thread A는 lock을 반납하기 때문에 Thread B가 synchronized 블락으로 접근이 가능하게 되었다.


notify(), notifyAll()

notify(), notifyAll()는 인스턴스의 WAIT SET에서 대기중인 다른 Thread를 깨우는 역할을 한다. notify는 WAIT_SET에 있는 임의의 한개의 Thread 를 다시 RUNNABLE 상태로 변경하고, notifyAll()의 경우는 WAIT_SET에 있는 모든 Thread를 RUNNABLE상태로 변경하는 차이가 있다.

  • 인스턴스의 WAIT SET에 있는 대기중인 Thread 를 깨운다.
  • 깨어난 Thread 는 RUNNABLE상태로 변경되어 다시 실행된다.
  • notify는 하나의 Thread, notifyAll은 모든 Thread 를 깨운다.



위에 wait()메소드에 이어서 Thread B가 notify()를 호출하기 직전의 상황이다. WAIT SET에는 Thread A가 대기중에 있다.



Thread B에 의해서 notify()가 호출되면 인스턴스 WAIT SET에 있는 Thread 들 중 임의의 한개를 깨우게 된다. 위 그림의 경우 대기중인 Thread 가 한개이기 때문에 Thread A가 깨어나게 된다. notifyAll이라면 WAIT SET에 있는 모든 Thread 가 깨어난다.



notify()에 의해서 Thread A가 다시 RUNNABLE 상태가 되어 다시 인스턴스의 접근을 시도한다. 그림은 아직 Thread B가 lock을 갖고 있지만, Thread B가 lock을 해제하게 되면 다시 Thread A가 lock을 획득하게 된다.


요점정리

  • wait(), notify(), notifyAll()은 synchronized 내부(lock을 소유)한 Thread 가 수행한다.
  • 만약 lock이 없는 Thread가 수행하는 경우 IlegalMonotorStateException이 발생한다.
  • wait(), notify(), notifyAll()는 Object에 메소드 이다. 
  • wait()는 Thread 를 WAIT SET으로 대기하게 한다.
  • notify(), notifyAll()은 WAIT SET에서 대기중인 Thread 를 깨운다.


이 글을 공유하기

댓글

Email by JB FACTORY