mutex, semaphore, conditional variable, monitor의 차이점

mutex, semaphore, conditional variable, monitor의 차이점에 대해 서술해보겠다.
참고로 아래의 내용은 특정 OS에 국한된 특수한 내용이 아니라 general concept에 대한 내용이다.

  mutex는 locking mechanism이다. 즉 mutual exclusion을 위한 것으로서 lock의 owner가 존재한다. 교과서적으로는(이론적으로는) mutex와 binary semaphore를 같게 취급하는 경우도 있지만, 실제 implementation에서는 mutex는 ownership의 개념이 있다는 측면에서 다르다. binary semaphore는 누구나 up하고 down할 수 있지만, mutex는 lock의 owner만 release할 수 있다.

  semaphore는 signal mechanishm이다. semaphore count가 0일 경우 non-signaled, 1이상일 경우 signaled상태라고 할 수 있다. 누구나 semaphore count를 up 혹은 down할 수 있다. semaphore는 mutex보다 general하게 사용될 수 있다. semaphore도 locking mechanism으로서 사용될 수 있겠지만 mutex를 사용하는 것이 좀 더 옳은 방법일 것이다. 
  semaphore는 생산자-소비자 모델에서 활용될 수 있을 것이다. 여러개의 생산자 thread, 여러개의 소비자 thread가 있을 때 생산자는 생산이 완료되면 semaphore를 up하고, 소비자는 소비를 하기전에 down하는 식으로 생산자-소비자 모델을 구현할 수 있을 것이다.

  conditional variable은 특정 조건이 성립할 때까지 wait하고, 조건이 성립할 때 wait하고 있는 thread 1개 혹은 여러개를 깨울 수 있는 mechanism이다. conditional variable은 보통 mutex와 associated되어 사용된다. semaphore와 다른 점은 semaphore는 up한 다음 down하면 signal을 받지만, condition variable은 signal한 다음 wait하면 signal을 받지 못한다. 
  conditional variable는 생산자-소비자 모델에서 유용하게 쓰일 수 있다. 생산하고 소비할 resource를 저장하고 받아오는 부분에서 동기화가 필요한 경우 단순히 semaphore만을 이용해서는 구현이 불가능하다. 이럴 경우, mutex와 semaphore를 함께 사용하면 사용이 가능하다. 근데 대부분의 경우 resource memory에는 제한이 있다. 따라서 만약 memory가 full일 경우에는 writer thread는 reader thread가 resource를 소비할 때까지 대기를 해야한다. 근데 semaphore + mutex의 구조로는 이를 해결할 수 없다. 스핀락을 이용할 수 있지만 이는 비효율적일 수 있고, 추가적인 semaphore를 이용해서 해결을 하려고 하면, reader thread에서 resource memory가 full일 경우에만 up해주는 식으로 구현을 할 수도 있을 텐데, 만약 memory가 full인지 확인하는 부분이 동기화가 안되면 writer thread 수보다 많은 up이 이루어져서 나중에 memory full 상태인데도 writer thread가 동작할 수 있는 문제가 발생할 수 있다. 이를 해결하려면 reader thread에서 memory full을 확인하는 것에 대해서도 mutex를 통해 동기화를 해야한다.... 문제가 매우 복잡해진다 ㅠㅠ 
  따라서 이럴 때는 semaphore가 아닌 conditional variable을 사용하면 쉽게 문제를 해결 할 수 있다. reader thread가 resource를 소비할 때 무조건 writer thread에서 signal을 보내주면 된다. 이렇게 하면 memory full이라서 wait하고 있는 writer thread(들)에게 signal이 가서 생산을 다시 시작하게 할 수 있다. signal 이후에 wait를 호출한 writer thread에 대해서는 signal이 적용안되기 때문에 semaphore를 이용했을 경우의 문제또한 발생하지 않게 된다.

  monitor는 conditional variable과 mutex를 이용하여 mutual exclusion과 waiting for certain condition 기능을 수행해주는 class나 module 따위를 의미한다. mutex랑 associated된 conditional variable과 monitor는 사실상 하는 역할이 같다.
  이러한 기능이 보통 C#이나 JAVA에서는 monitor의 이름으로 사용되고, windows api나 pthread library에서는 conditional variable이라는 이름으로 사용된다. 사실상 하는 역할이 같다고 봐도 될 것 같다. 
  추가적으로 conditional variable은 엄밀하게 말하면 waiting for certain condition을 위함이지만, 대부분의 경우 conditional variable이 mutex랑 항상 associated되어 쓰여서 conditional variable associated with mutex를 그냥 conditional variable이라고 부르는 경우가 많은 것 같다.

댓글