- 상호 배제: 오직 하나의 프로세스 또는 스레드만이 임계 구역에 진입하고 실행할 수 있음을 보장
- 한정 대기: 임계 구역에 들어가고자 하는 프로세스가 무한히 기다리는 것을 허용하지 않음
→ 특정 프로세스가 임계 구역을 독점적으로 사용하는 것을 방지- 진행의 융퉁성: 한 프로세스가 다른 프로세스의 일을 방해하지 않아야 함
→ 프로세스가 임계 구역을 사용하지 않을 때, 다른 프로세스가 해당 구역에 접근하여 작업할 수 있어야 한다.
- lock값이 1이면 프로세스 1이, 2이면 프로세스 2가 임계구역 사용하게된다.
그러나, 한 프로세스는 다른 프로세스가 임계구역에 진입했다가 나온 다음에야 다시 진입 가능한 lockstep synchronization이 발생한다.
→ 경직된 동기화(lockstep synchronization): 프로세스의 진행이 다른 프로세스로 인해 방해받는 현상
- lock(): 프로세스나 스레드는 lock()을 호출하여 공유 자원에 대한 접근 권한을 획득
→ 다른 프로세스나 스레드는 해당 자원이 반환될 때까지 대기- unlock(): 공유 자원을 사용한 프로세스나 스레드는 작업을 완료한 후 unlock()을 호출하여 공유 자원에 대한 접근을 해제
→ 다른 프로세스나 스레드가 공유 자원에 대한 접근 권한을 획득할 수 있게 된다.
공유 자원을 사용하고 있는 프로세스 또는 스레드의 수를 공통으로 관리하는 정수값을 이용하여 동기화
→ 다중 프로세스 또는 다중 스레드가 임계 영역에 동시에 접근할 수 있는지 여부를 제어
- wait(): 세마포어의 값을 1씩 감소시키며, 공유 자원에 접근하려는 상태
- 세마포어 값이 음수가 되면, 해당 공유 자원에 접근할 수 없는 상태를 의미한다.
접근을 시도한 프로세스 또는 스레드는 대기열로 들어가게 되고, signal()에 의해 깨어난다.- signal(): 세마포어의 값을 1씩 증가시키며, 해당 공유 자원 사용을 완료한 상태
- 만약 대기열에 프로세스가 있다면, 세마포어 값을 증가시키고 대기열에 있는 프로세스 중 하나를 깨워 작업을 수행
종류
- 바이너리 세마포어: 프로세스 또는 스레드의 수를 관리하는 정수값이 0 또는 1만 가질 수 있는 세마포어
- 뮤텍스와 비슷한 방식으로 동작
→ 뮤텍스: 잠금기반으로 상호배제가 일어나는 '잠금 메커니즘'
→ 바이너리 세마포어: 신호기반으로 상호배제가 '신호 메커니즘'- 카운팅 세마포어: 프로세스 또는 스레드의 수를 관리하는 정수값이 여러 개의 값을 가질 수 있는 세마포어
- 자원 소유 가능 여부
- 뮤텍스: 자원을 소유할 수 있으며, 뮤텍스를 소유한 프로세스나 스레드만이 해당 뮤텍스를 해제할 수 있다.
- 세마포어: 자원을 소유할 수 없으며, 세마포어 소유권을 갖고 있지 않은 프로세스나 스레드도 세마포어를 해제할 수 있다.
- 동기화 대상 수
- 뮤텍스: 동기화 대상이 하나뿐인 경우에 주로 사용
- 세마포어: 여러 개의 동기화 대상을 관리하는 데 사용
- Lock 획득 (Acquisition): 스핀락을 획득하려는 스레드는 스핀락을 획득하기 위한 시도
- Busy Waiting (스핀 대기): 스핀락을 획득하려는 스레드는 스핀락을 얻을 때까지 무한 루프를 돌면서 대기
→ 스레드가 스핀락을 획득할 때까지 지속적으로 CPU 자원을 소모- Unlock 반납 (Release): 스핀락을 보유하고 있는 스레드는 임계 구역을 빠져나올 때 스핀락을 반납
둘 이상의 프로세스 또는 스레드가 공유 자원에 안전하게 접근할 수 있도록 공유 자원을 숨기고 해당 공유 자원에 대한 인터페이스만 제공
→ 모니터 큐를 통해 접근 프로세스나 스레드를 순차적으로 처리
- 구현 난이도: 모니터는 상대적으로 쉽게 구현할 수 있으며, 공유 자원을 추상화한 인터페이스를 제공하는 방식으로 구축된다.
반면 세마포어는 정수값을 기반으로 구축되어 구현이 어려울 수 있다.- 상호배제: 모니터는 내부에서 공유 자원에 대한 접근을 한 번에 하나의 프로세스 또는 스레드만 허용하므로 상호배제 문제를 내부에서 처리한다.
세마포어는 명시적으로 상호배제를 해결해야 한다.