2008년 03월 11일
[Java][synchronized] wait 와 while
작성자 : 김민석 ( lemonfish at gmail dot com )
어떤 사람으로 부터 질문을 받았다.
"Java API 에 wait 을 쓸때는 while 과 함께 쓰라고 분명히 되있는데 왜 그래야 하냐?" 라는 것이였다.
그래서 문제가 되는 Java API document 의 한 부분을 발췌한 것이 아래이다.
이 글은 JDK 5.0 의 API document 에서 발췌한 것인데. 1.4 API document 에는 없는 부분이다. Sun 에서 문서화를 할 때 중점을 두는 부분이 예제의 추가라는 걸 알수 있다.(물론 문서화에는 애매한 부분을 좀더 명확하게 기술하는 부분도 들어간다.)
Object 클래스의 wait 메서드에 대한 설명중 한부분이다. 개발자들이 어렵게 생각하니 친절하게도 이런 용도로 쓸때는 이런식으로 하면된다. 라는 식으로 예제를 만들어놓았다.
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while(<condition does not hold>)
obj.wait(timeout, nanos);
...
// Perform action appropriate to condition
}
결론은 이렇다.
세라비 님의 교정을 통해 수정한 내용입니다.
wait 을 걸어놔도 예기치 않게 block 이 깨지는 수가 있으니 wait 해야하는 조건을 while 의 <condition does not hold> 부분에 넣어서 보호하라는 예기다. 물론 wait 해야하는 조건이 아닐경우 while 을 빠져나와 정상수행을 하게 된다.
유명한 예제인 생산자 - 소비자 를 예로 들어 보자.
public synchronized String get(){
while(bMsg == false){
//bMsg 는 생산자 또는 소비자가 작업을 완료했음을 알리는 플래그
try{ wait(); } catch(Exception e){}
.... some jobs ...
return msg;
}
}
위 코드는 상대의 작업이 완료되었을 때 자신의 처리를 수행하도록 되어있다. 때문에 상대의 작업 완료를 검사하고 작업이 완료되지 않았을 경우 wait 을 통해 대기하게 된다. wait 의 경우 notify 나 notifyAll 을 통해 대기가 해제되는데 문제는 코드상에 나와있지 않은 어떠한 요소(interrupts and spurious wakeups) 로 인해 wait 이 해제될 수 있다는 것이다. 따라서 작업이 완료되었을때 notify 나 notifyAll 을 호출하여 wait 을 해제하도록 하였다 하더라도 확실히 그것이 작업완료로 인한 대기해제인지는 보장이 되지 않는다는 것이다. 때문에 wait 이 해제 되더라도 완료플래그를 반드시 다시 검사하여야 한다. while 은 그러한 조건검사 수행을 위해 사용된다.
# by | 2008/03/11 19:42 | Java | 트랙백 | 덧글(6)





☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
복받으세요.^^