왜 wait() 메소드는 항상 synchronized 블록 안에 있는거죠?

조회수 2775회

Object.wait()메소드를 발생시키려면 메소드가 반드시 synchronized 블록 안에 있어야 한다는 것은 모두가 아는 사실입니다. 그렇지 않으면 IllegalMonitorStateException이 발생하겠죠. 왜 이러한 제한을 두는 이유가 무엇이죠? wait()메소드가 monitor를 release하는 것은 알고 있습니다만, 왜 synchronized 블록을 따로 만든 후에 wait()메소드를 호출하는 방법을 통해서 명시적으로 monitor를 얻어야 하는 것인가요?

wait()을 동기화 블럭 외부에서 실행한다면, 즉 의미를 유지한 채, 호출 스레드를 지연 시킬때 발생하는 잠재적 위험은 무엇입니까?

1 답변

  • 좋아요

    0

    싫어요
    채택 취소하기

    Wait()는 notify()메소드 또한 존재할 때 의미가 있는 메소드입니다. 그래서 항상 스레드간의 상호작용과 관련이 있으며 제대로 작동하기 위해서는 synchronization이 필요한거죠. 이러한 과정들이 암시적이어야 하는 것이 아닌가라고 생각할 수 있지만 다음과 같은 이유 때문에 전혀 도움이 되지 않습니다:

    의미상 항상 wait()하는 것만은 아닙니다. 만족시켜야할 condition이 존재하고요 그렇지 않다면 만족될 때까지 wait합니다. 다음과 같이 작동하겠죠.

    if(!condition){
        wait();
    }
    

    그러나 condition이 여러 스레드에 의해 설정된다면 제대로 된 동작을 위해서는 synchroniztion이 필요합니다.

    스레드가 waiting 동작을 멈추는 것이 꼭 condition이 true가 되는 것을 의미하는 것은 아니기 때문에 몇 가지 더 잘못된 부분이 있습니다:

    • 거짓된 wakeup을 받을 수 있습니다(스레드가 특별한 신호를 전달받지 않고 waiting상태로부터 깨어나는 것을 의미합니다) 혹은
    • condition이 true로 설정되었는데 waiting스레드가 깨어날 때 쯤에 제 3의 스레드가 condition을 다시 false로 변경하는 상황(그리고 monitior를 다시 얻는)

    이러한 경우들을 해결하기 위해서 필요한 것은 항상 아래 코드를 변형해서 사용하는 것입니다:

    synchronized(lock){
        while(!condition){
            lock.wait();
        }
    }
    

    Synchronization에 얽매이지 않고 java.util.concurrent 패키지가 제공하는 개념들로 해결하면 더욱 좋겠네요.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)