빽 투더 기본기 [OS 5편]. 뮤텍스와 세마포어
이 글에서는 저번 글에 이어, 동기화 기법 중 하나인 뮤텍스와 세마포어에 대해 적어본다.
1. 뮤텍스 (MUTual Exclusion)
1.1. 뮤텍스란?
뮤텍스는 상호배재라는 뜻으로, 이전 글에서와 마찬가지로 동기화 기법 중 하나이다.
뮤텍스는, 쓰레드 간 임계 영역의 동기화를 위한 기법이다.
1.2. 어떻게 구현하는가?
lock
과 unlock
의 개념이 등장한다.
임계 영역에 먼저 들어가는 쓰레드가 lock
을 걸면, 이 쓰레드가 unlock
을 할 때 까지, 다른 쓰레드들은 임계 영역에 들어가지 못하도록 하는 것이다.
즉, 임계 영역에 들어가는 쓰레드는 임계 영역 앞뒤에 lock
과 unlock
을 해야한다.
v = 1;
def lock():
while v != 1
# 2. 이미 다른 쓰레드에 의해 선점된 경우, v=0 이므로, 이 루프를 계속 돈다.
if (v==1)
# 4. 앞서 선점한 쓰레드가 락을 풀면 v=1 이므로, 루프를 탈출한다.
break;
# 1. 먼저 선점한 쓰레드가 v=0 으로 만들어, 락을 잠가버린다.
v = 0;
def unlock():
# 3. 할 일을 하고나온 쓰레드는 v=1 로 만들어, 락을 푼다.
v = 1;
lock() # 들어갈 때 락을 잠그고
# critical section
unlock() # 나갈 때 락을 푼다.
2. 세마포어 (Semaphore)
2.1. 세마포어란?
뮤텍스와 마찬가지로, 동기화 기법 중 하나다.
다만, 뮤텍스는 임계 영역에 들어가는 쓰레드가 하나라면, 세마포어는 복수 개가 가능하다.
2.2. 어떻게 구현하는가?
wait
과 signal
의 개념이 등장한다.
일반적으로, wait
이 먼저 호출되어, 임계 영역에 들어갈 수 있는지 확인한다. 혹은, 먼저 실행되어야하는 프로세스가 실행되었는지를 확인한다. 조건에 만족하면, wait
을 빠져나와 임계영역으로 들어간다.
이후 signal
이 호출되어, 임계 영역을 빠져나왔음을 알린다.
S = 3 # 임계 영역에 들어갈 수 있는 쓰레드, 프로세스는 3개다.
def wait(S):
S--
if S < 0:
# add this process into Waiting Queue (Sleep or Block)
def signal(S):
S++
if S > 0:
# pop the process from the Waiting Queue (Wake up)
wait(S)
# critical section
signal(S)
2.3. 데드락(Dead Lock) 문제
세마포어는 데드락 문제가 있는데, 예를 들면 다음과 같은 상황이다.
P0 P1
wait(S); wait(Q);
wait(Q); wait(S);
... ...
signal(S); signal(Q);
signal(Q); signal(S);
각 프로세스의 첫째줄이 동시에 실행될 경우, 서로 wait
상태로, 다른 쪽에서 signal
을 해주기 전까지 기다리게 되는데, 둘 다 모두 계속 wait
에 머물러 있으므로, 프로그램은 절대 끝나지 않는다. 이 현상이 데드락(교착상태) 다.
따라서, 세마포어를 쓸 때는 이와 같은 문제를 유념해두고 사용해야한다.
3. 뮤텍스와 세마포어의 차이
이건… 면접의 흔한 질문이라고 한다. 검색해보면 이 내용에 대한게 많다.
아무튼 정리를 해보면.. 가장 큰 차이점은 이거라고 한다.
세마포어는 뮤텍스가 될 수 있지만 (S = 1 인 경우), 뮤텍스는 세마포어가 될 수 없다.
뮤텍스는 바이너리 값을 갖는 세마포어다.
지금까지 언급한 동기화 방법 외에도, 하드웨적 동기화, 모니터 등이 있지만, 생략하겠다.