본문 바로가기

자바의 정석

[자바의 정석 2권] wait()와 notify()

1) wait()와 notify()

- synchronized로 동기화해서 공유 데이터를 보호하는 것 까지는 좋은데,

  특정 쓰레드가 객체의 락을 가진 상태로 오랜 시간을 보내지 않도록 하는 것도 중요하다.

  만일 계좌에 출금할 돈이 부족해서 한 스레드가 락을 보유한 채로 

  돈이 입금될 때까지 오랜 시간을 보낸다면,

  다른 쓰레드들은 모두 해당 객체의 락을 기다리느라 다른 작업들도 원활히 진행되지 않을 것이다. 

 

- 이러한 상황을 개선하기 위해 고안된 것이 바로 wait()와 notify()이다.

  동기화된 임계 영역의 코드를 수행하다가 작업을 더 이상 진행할 상황이 아니면,

  일단 wait()을 호출하여 쓰레드가 락을 반납하고 기다리게 한다. 

 

- 그러면 다른 쓰레드가 락을 얻어 해당 객체에 대한 작업을 수행할 수 있게 된다.

  나중에 작업을 진행할 수 있는 상황이 되면 notify()를 호출해서,

  작업을 중단했던 쓰레드가 다시 락을 얻어 작업을 진행할 수 있게 한다. 

 

- 오래 기다린 쓰레드가 락을 얻는다는 보장은 없다.

  wait()가 호출되면, 실행 중이던 쓰레드는 해당 객체의 대기실(waiting pool)에서 통지를 기다린다.

  notify()가 호출되면, 해당 객체의 대기실에 있던 모든 쓰레드 중에서 임의의 쓰레드만 통지를 받는다.

  

- notifyAll()은 기다리고 있는 모든 쓰레드에게 통보를 하지만,

  그래도 lock을 얻을 수 있는 것은 하나의 쓰레드일 뿐이고,

  나머지 쓰레드는 통보를 받긴 했지만, lock을 얻지 못하면 다시 lock을 기다리는 신세가 된다. 

 

- wait()와 notify()는 특정 객체에 대한 것이므로 Object 클래스에 정의되어 있다.