Skip to content

Latest commit

 

History

History
597 lines (417 loc) · 25 KB

보충2__동기화 도구들.md

File metadata and controls

597 lines (417 loc) · 25 KB

보충2__동기화 도구들


보충2.1 🍂 배경 jehong

다음 그림과 보기를 참고해 1, 3번 문제의 빈칸을 채우고 2번 문제에 답해주세요.

<보기>

경쟁 상황(race condition),

동기화, 프로세스, 조작, 진행, 조정

증가, 감소

4, 5, 6, count

  1. 두 개의 프로세스 생산자와 소비자 프로세스는 각각 count++와 count--를 수행합니다. count라는 변수는 버퍼에 새 항목을 추가할 때마다 _____되고 버퍼에서 한 항목을 꺼낼 때마다 _____되는 것으로, 현재 count는 5입니다. 다음 그림에서 register1과 register2는 한 CPU만 접근할 수 있는 로컬 레지스터 중 하나입니다. count++와 count-- 코드를 병행하여 실행해 아래처럼 count가 _____이/가 되었습니다. (빈칸채우기)

  2. count 값이 정확한가요? 정확하지 않다면 실제로는 몇 개의 버퍼가 채워져 있어야하며 왜 부정확한지 설명해주세요. (주관식)

  3. __________이란 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황입니다. __________으로부터 보호하기 위해 한순간에 하나의 프로세스만이 변수 _____ 를 조작하도록 보장해야하며, 이를 위해 프로세스들이 _____되록 할 필요가 있습니다. (빈칸채우기)

📄 답지

다음 그림과 보기를 참고해 1, 3번 문제의 빈칸을 채우고 2번 문제에 답해주세요.

<보기>

경쟁 상황(race condition),

동기화, 프로세스, 조작, 진행, 조정

증가, 감소

4, 5, 6, count

  1. 두 개의 프로세스 생산자와 소비자 프로세스는 각각 count++와 count--를 수행합니다. count라는 변수는 버퍼에 새 항목을 추가할 때마다 증가되고 버퍼에서 한 항목을 꺼낼 때마다 감소되는 것으로, 현재 count는 5입니다. 다음 그림에서 register1과 register2는 한 CPU만 접근할 수 있는 로컬 레지스터 중 하나입니다. count++와 count-- 코드를 병행하여 실행해 아래처럼 count가 4이/가 되었습니다. (빈칸채우기)

    증가, 감소, 4

  2. count 값이 정확한가요? 정확하지 않다면 실제로는 몇 개의 버퍼가 채워져 있어야하며 왜 부정확한지 설명해주세요. (주관식)

    count++와 count--를 병행하게 실행하는 것은 해당 문장들을 임의의 순서로 뒤섞어 순차적으로 실행하는 것과 동일합니다. 따라서 count는 실행 순서에 따라 4나 6의 부정확한 값을 갖게되며 실제로는 5개의 버퍼가 채워져 있습니다. 이는 두 개의 프로세스가 동시에 변수 count를 조작하도록 허용했기 때문입니다.

  3. 경쟁 상황(race condition)이란 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황입니다. 경쟁 상황으로부터 보호하기 위해 한순간에 하나의 프로세스만이 변수 count 를 조작하도록 보장해야하며, 이를 위해 프로세스들이 동기화되록 할 필요가 있습니다. (빈칸채우기)

    경쟁 상황, 경쟁 상황, count, 동기화



보충2.2 🍂 임계구역 문제 taelee

  1. 각 프로세스는 _____ 이라고 부르는 코드 부분을 포함하고 있고 그 안에서는 적어도 하나 이상의 다른 프로세스와 공유하는 데이터에 접근하고 갱신할 수 있다.

  2. _______는 프로세스들이 데이터를 협력적으로 공유하기 위하여 자신들의 활동을 동기화할 때 시용할 수 있는 프로토콜을 설계하는 것이다.

  3. 임계구역 문제를 해결하기 위해서는 다음 세가지 요구 조건을 충족시켜야 한다.

  • ________: 임계구역에는 동시에 한 프로세스만 접근가능함
  • ________: 유한한 시간 내에 임계구역에 들어갈 프로세스를 정해야함
  • ________: 프로세스가 임계구역을 들어가기 위한 요청 이후 실제 진입까지의 과정이 유한한 시간내에 일어나야함
📄 답지
  1. 각 프로세스는 _____ 이라고 부르는 코드 부분을 포함하고 있고 그 안에서는 적어도 하나 이상의 다른 프로세스와 공유하는 데이터에 접근하고 갱신할 수 있다. 임계구역 (critical section)

  2. _______는 프로세스들이 데이터를 협력적으로 공유하기 위하여 자신들의 활동을 동기화할 때 시용할 수 있는 프로토콜을 설계하는 것이다. 임계구역 문제

  3. 임계구역 문제를 해결하기 위해서는 다음 세가지 요구 조건을 충족시켜야 한다.

  • ________: 임계구역에는 동시에 한 프로세스만 접근가능함
  • ________: 유한한 시간 내에 임계구역에 들어갈 프로세스를 정해야함
  • ________: 프로세스가 임계구역을 들어가기 위한 요청 이후 실제 진입까지의 과정이 유한한 시간내에 일어나야함 (스케쥴링에서 기아문제같은것이 일어나지 않는것을 말하는 듯) 상호 배제(Mutual Exclusion) 진행(Progress) 한정된 대기(Bounded Waiting)


보충2.3 🍂 Peterson의 해결안 yeosong

스크린샷 2020-11-08 오후 10 45 33

1. 피터슨 해결법의 단점은 무엇인가요?

2. 피터슨 해결법의 한계는 무엇인가요?

📄 답지

피터슨의 해결법은 들어가길 원하는지 표시하는 flag와 차례인지 표시하는 turn을 동시에 써서 임계구역 문제 해결을 위한 3가지 요구조건인 1.상호배제 2.진행 3.유한대기의 조건을 모두 만족시킵니다.

피터슨 해결법의 단점은 무엇인가요?

busy waiting으로 자원 낭비.
busy waiting이란 대기를 하는 동안 실제로 하는 일은 없는데 CPU를 계속 사용하며 대기하는 것으로, spin lock이라고도 한다.

피터슨 해결법의 한계는 무엇인가요?

데이터 무결성 문제를 일으킬 수 있음 / 상호배제 조건 미달
현대적인 아키텍쳐에서는 성능 향상을 위해 작업 순서를 바꿀 수 있기 때문에
다중스레드가 데이터를 공유하는 과정에서 실행할 명령어들의 순서를 바꿔버리면 상호배제 조건이 충족되지 않음.



보충2.4 🍂 뮤텍스 kukim

  1. Mutex lock는 특정 코드 영역의 쓰레드를 실행할 때 한번에 하나 이상의 쓰레드만 실행 가능하도록 하는 방법이다. (O / X)

  2. 아래의 코드 결과는 서술하시오.

// exam2.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
int g_count = 0;  // 쓰레드 공유자원.
 
void *t_function(void *data)
{
    int i;
    char* thread_name = (char*)data;
    // critical section
    g_count = 0;   // 쓰레드마다 0부터 시작.
    for (i = 0; i < 3; i++)
    {
        printf("%s COUNT %d\n", thread_name, g_count);
        g_count++;  // 쓰레드 공유자원, 1증가.
        sleep(1);
    }
}
int main()
{
    pthread_t p_thread1, p_thread2;
    int status;
 
    pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
    pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
 
    pthread_join(p_thread1, (void *)&status);
    pthread_join(p_thread2, (void *)&status);
}

// compile
// gcc exam2.c -o exam2
  1. 아래의 코드 결과를 서술하시오
// exam3.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
// 뮤텍스 객체 선언
pthread_mutex_t mutex_lock;
 
int g_count = 0;  // 쓰레드 공유자원.
 
void *t_function(void *data)
{
    int i;
    char* thread_name = (char*)data;
    
    
 
    pthread_mutex_lock(&mutex_lock);
 
    // critical section
    g_count = 0;   // 쓰레드마다 0부터 시작.
    for (i = 0; i < 3; i++)
    {
        printf("%s COUNT %d\n", thread_name, g_count);
        g_count++;  // 쓰레드 공유자원
        sleep(1);
    }
 
    pthread_mutex_unlock(&mutex_lock);
}
int main()
{
    pthread_t p_thread1, p_thread2;
    int status;
    // 뮤텍스 객체 초기화, 기본 특성으로 초기화 했음
    pthread_mutex_init(&mutex_lock, NULL);
 
    pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
    pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
 
    pthread_join(p_thread1, (void *)&status);
    pthread_join(p_thread2, (void *)&status);
}

// compile
// gcc exam3.c -o exam3 -lpthread

Mutex 코드 참고(문제 다 풀고 들어가세요) https://bitsoul.tistory.com/172

📄 답지
  1. Mutex lock는 특정 코드 영역의 쓰레드를 실행할 때 한번에 하나 이상의 쓰레드만 실행 가능하도록 하는 방법이다. (O / X)
  • 정답 : X , 한번에 하나의 쓰레드만 실행 가능하도록 하는 방법이다.
  1. 아래의 코드 결과는 서술하시오.
// exam2.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
int g_count = 0;  // 쓰레드 공유자원.
 
void *t_function(void *data)
{
    int i;
    char* thread_name = (char*)data;
    // critical section
    g_count = 0;   // 쓰레드마다 0부터 시작.
    for (i = 0; i < 3; i++)
    {
        printf("%s COUNT %d\n", thread_name, g_count);
        g_count++;  // 쓰레드 공유자원, 1증가.
        sleep(1);
    }
}
int main()
{
    pthread_t p_thread1, p_thread2;
    int status;
 
    pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
    pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
 
    pthread_join(p_thread1, (void *)&status);
    pthread_join(p_thread2, (void *)&status);
}

// compile
// gcc exam2.c -o exam2
  • 정답 : Thread1, 2 모두 g_count 쓰레드 자원을 공유하기 때문에 매번 exam2를 실행할 때 마다 이상한 값이 나온다.
  1. 아래의 코드 결과를 서술하시오
// exam3.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
// 뮤텍스 객체 선언
pthread_mutex_t mutex_lock;
 
int g_count = 0;  // 쓰레드 공유자원.
 
void *t_function(void *data)
{
    int i;
    char* thread_name = (char*)data;
    
    
 
    pthread_mutex_lock(&mutex_lock);
 
    // critical section
    g_count = 0;   // 쓰레드마다 0부터 시작.
    for (i = 0; i < 3; i++)
    {
        printf("%s COUNT %d\n", thread_name, g_count);
        g_count++;  // 쓰레드 공유자원
        sleep(1);
    }
 
    pthread_mutex_unlock(&mutex_lock);
}
int main()
{
    pthread_t p_thread1, p_thread2;
    int status;
    // 뮤텍스 객체 초기화, 기본 특성으로 초기화 했음
    pthread_mutex_init(&mutex_lock, NULL);
 
    pthread_create(&p_thread1, NULL, t_function, (void *)"Thread1");
    pthread_create(&p_thread2, NULL, t_function, (void *)"Thread2");
 
    pthread_join(p_thread1, (void *)&status);
    pthread_join(p_thread2, (void *)&status);
}

// compile
// gcc exam3.c -o exam3 -lpthread
  • 정답 : Mutex Lock이 걸려서 Thread1이 먼저 실행된다면 Thread2는 1이 끝날 때 까지 임계영역에 들어가 수 없기 때문에 count 0 1 2를 출력하고 그 다음 Thread2의 count가 0 1 2 를 출력한다. 만약 Thread2가 먼저 실행된다면 앞에 설명한 것과 반대로 출력된다.

Mutex 코드 참고 https://bitsoul.tistory.com/172



보충2.5 🍂 세마포 mihykim

문제1 🏃‍ 세마포 정의

  • [1-1] 다음중 세마포의 정의로 가장 적절한 것은?
    • a. '세'초가 '마'싯는거 '포'기함
    • b. 순차적으로 리소스에 접근 허용이 가능한 개수를 의미하는 정수 변수
    • c. 동시에 리소스에 접근 허용이 가능한 개수를 의미하는 실수 변수
    • d. 동시에 리소스에 접근 허용이 가능한 개수를 의미하는 정수 변수
  • [1-2] 다음 중 세마포에서 가능한 모든 연산에 해당하는 것은? (단, 초기화 제외)
    • a. eat(), pray(), love()
    • b. love(), sick(), girl()
    • c. signal(), twice()
    • d. wait(), signal()

문제2 🏃‍ P연산 / V연산

<보기>
S > 0  S >= 0  S < 0  S <= 0  S == 0  S++;  S--;
  • [2-1] 보기에서 아래 내용에 해당되는 적절한 범위를 골라주세요

    • 새로운 스레드가 임계영역(Critical Section)에 진입할 수 없는 범위 :     
    • 새로운 스레드가 임계영역(Critical Section)에 진입할 수 있는 범위 :     
  • [2-2] 보기에서 💙(a)와 (b)💙에 들어갈 적절한 수식을 골라주세요

wait(S) {
    while (💙(a)💙)
      ; //busy wait
    S--;
}
// P(S) : S값 검사 (공유자원을 획득하기 위한 과정)

signal(S) {
  💙(b)💙;
}
// V(S) : S값 증가 (공유자원을 다 사용하고 나서 반납하는 과정)

문제3 🏃‍ 세마포 종류

  • 다음 설명을 읽고 적절한 세마포 종류를 적어주세요(단답식, 1등 +50점)
    • 0과 1의 값만 가능해서, 쿠키교수님께서 설명해주신 'Mutex락'과 유사하게 동작하는 세마포어 : ㅇㅇ 세마포어(...... semaphores)
    • 영역(domain)에 제한이 없어 총 가용한 자원의 개수로 초기화되는 세마포어 : ㅇㅇㅇ 세마포어(........ semaphorse)

문제4 🏃‍ 스핀락

✨스핀락(Spin Lock)이란?
- 임계구역(Critical Section) 진입이 불가할 때 가능할 때까지 whlie문을 돌면서 재시도하는 방식으로 구현된 락
- OS의 스케줄링 지원을 받지 않기 때문에, 해당 스레드에 대한 문맥교환(Context Switching)이 일어나지 않음
- 만약, 스핀락이 오랜 시간을 소요한다면 바쁜 대기(Busy Waiting) 현상으로 인해 비효율적임
- 만약, 스핀락이 오랜 시간을 소요하지 않는다면 문맥교환(Context Switching)에 따른 오버헤드를 줄일 수 있어서 효율적임
  • [4-1] 위 설명을 읽고, 스핀락이 단일 프로세서 시스템에 적합하지 않은 이유를 설명해주세요(+150점)
    • 이유 :
  • [4-2] 위 설명을 읽고, 스핀락이 다중 처리기 시스템에서는 종종 사용되는 이유를 설명해주세요(+200점)
    • 이유 :
📄 답지

문제1 🏃‍ 세마포 정의

  • [1-1] 다음중 세마포의 정의로 가장 적절한 것은?
    • d. 동시에 리소스에 접근 허용이 가능한 개수를 의미하는 정수 변수
  • [1-2] 다음 중 세마포에서 가능한 모든 연산에 해당하는 것은? (단, 초기화 제외)
    • d. wait(), signal()

문제2 🏃‍ P연산 / V연산

  • [2-2] 보기에서 💙(a)와 (b)💙에 들어갈 적절한 수식을 골라주세요

    • 새로운 스레드가 임계영역(Critical Section)에 진입할 수 없는 범위 : S <= 0
    • 새로운 스레드가 임계영역(Critical Section)에 진입할 수 있는 범위 : S > 0
  • [2-2] 보기에서 💙💙💙에 들어갈 적절한 수식을 골라주세요

wait(S) {
    while (💙S <= 0💙)
      ; //busy wait
    S--;
}
// P(S) : S값 검사 (공유자원을 획득하기 위한 과정)

signal(S) {
  💙S++;💙
}
// V(S) : S값 증가 (공유자원을 다 사용하고 나서 반납하는 과정)

문제3 🏃‍ 세마포 종류

  • 다음 설명을 읽고 적절한 세마포 종류를 적어주세요(단답식, 1등 +50점)
    • 0과 1의 값만 가능해서, 쿠키교수님께서 설명해주신 'Mutex락'과 유사하게 동작하는 세마포어 : 이진 세마포어(binary semaphores)
    • 영역(domain)에 제한이 없어 총 가용한 자원의 개수로 초기화되는 세마포어 : 카운팅 세마포어(counting semaphorse)

문제4 🏃‍ 스핀락

  • [4-1] 위 설명을 읽고, 스핀락이 단일 프로세서 시스템에 적합하지 않은 이유를 설명해주세요(+150점)
    • 이유 : 다른 스레드가 Lock을 가지고 있고 그 스레드가 Lock을 풀어주려면 싱글 CPU 시스템에서는 어차피 Context Switching이 일어나야 하기 때문에 스핀락의 장점이 사라지게 됩니다.
  • [4-2] 위 설명을 읽고, 스핀락이 다중 처리기 시스템에서는 종종 사용되는 이유를 설명해주세요(+200점)
    • 이유 : 하지만 멀티프로세서 시스템에서는 만약 스핀락의 기다리는 시간이 그리 길지 않다면, Busy Waiting을 하는 것이 Context Switching 을 통해 다른 프로세스로 전환되는데 드는 오버헤드보다 작을 것이기 때문에 종종 쓰입니다.


보충2.6 🍂 모니터 daelee

(1) 개념

✅ 문제 1. 전통의 오엑스문제
  • 모니터 구조는 모니터 안에 항상 하나의 프로세스만이 활성화되도록 보장해준다?! (O / X)
  • 모니터를 사용하면 프로그래머들이 동기화 제약조건을 직접 코딩하지 않아도 된다?! (O / X)

(2) 모니터 구조

모니터는 공유 자원 + 공유 자원 접근함수로 이루어져 있고, 2개의 큐를 가지고 있다. 각각 mutual exclusion(상호배타) 큐, conditional synchronization(조건동기) 큐이다.

  • 상호배타 큐는 공유 자원에 하나의 프로세스만 진입하도록 하기 위한 큐이다.
  • 조건동기 큐는 이미 공유자원을 사용하고 있던 프로세스가 일시정지 되면서 대기하는 큐이다.

✅ 문제 2-1. 모니터(1),(2),(3) 상태의 변화를 참고해 A, B 각각에 알맞은 함수를 적으세요.

monitor 구조


✅ 문제 2-2. 보기를 참고해 빈칸을 채워주세요.
보기 : Signal and wait, Signal 보내, Signal and continue, 찌릿찌릿찌릿찌릿, 난너를원해
  • ___(a)___ 기법을 사용한 모니터(3) 상황에서, 프로세스P는 프로세스Q가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다.

  • ___(b)___ 기법을 사용한 모니터(3) 상황에서, 프로세스Q는 프로세스P가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다.


(3) 세마포를 이용한 모니터 구현

✅ 문제 3. 세마포를 이용해 모니터를 구현할 때는 ___ and ___ 기법을 사용한다.

힌트 : 문제2-2에 정답이 숨어있어요


(4) Monitor vs Semaphore(보충개념)

  • 세마포는 모니터보다 낮은 수준(혹은 넓은 범위)의 개념이다. 세마포를 사용하여 모니터를 구현할 수 있기 때문이다. 세마포는 본질적으로 카운터일 뿐이다. 모니터는 이진 세마포다.
  • 모니터는 공중 화장실과 같다.
    • 한 번에 한 사람 만 입장 할 수 있기 때문이다. 다른 사람이 들어오지 못하도록 문을 잠그고 일을 본 다음 떠날 때 잠금을 해제한다.
  • 세마포는 자전거 대여소와 같다.
    • 자전거 대여소는 정해진 대수의 자전거를 가지고 있다. 자전거를 대여하려고하는데 자전거가 남아있는 경우 자전거를 탈 수 있다. 그렇지 않으면 기다려야한다.
    • 누군가 자전거를 반환하면 그때 다른 사람이 자전거를 탈 수 있다.
    • 자전거를 타던 사람은 자전거를 다른 사람에게 빌려줄 수 있다. 자전거 대여소는 자전거를 돌려받기만 하면 자전거를 반납하는 사람이 누구인지는 신경 쓰지 않기 때문이다.

출처 : Semaphore vs. Monitors - what's the difference?

📄 답지

1. 개념

✅ 문제 1. 전통의 오엑스문제
  • 모니터 구조는 모니터 안에 항상 하나의 프로세스만이 활성화되도록 보장해준다?! (O / X)
  • 모니터를 사용하면 프로그래머들이 동기화 제약조건을 직접 코딩하지 않아도 된다?! (O / X)

2. 모니터 구조

모니터는 공유 자원 + 공유 자원 접근함수로 이루어져 있고, 2개의 큐를 가지고 있다. 각각 mutual exclusion(상호배타) 큐, conditional synchronization(조건동기) 큐이다.

  • 상호배타 큐는 공유 자원에 하나의 프로세스만 진입하도록 하기 위한 큐이다.
  • 조건동기 큐는 이미 공유자원을 사용하고 있던 프로세스가 일시정지 되면서 대기하는 큐이다.

✅ 문제 2-1. 모니터(1),(2),(3) 상태의 변화를 참고해 A, B 각각에 알맞은 함수를 적으세요.

monitor 구조

정답 : A = wait(), B = signal()

모니터에서는 프로세스가 모니터 안에서 기다릴 수 있도록 Condition Variable 을 사용한다. 이 condition 변수는 wait()signal() 연산에 의해서만 접근할 수 있다.

wait()를 호출한 프로세스는 조건동기 큐로 들어가고, 공유자원을 사용하고 있는 다른 프로세스가 signal()을 호출해 줄 때까지 일시 중지된다.

참고로 자바는 모니터를 사용하는 대표적인 언어인데, 자바에서 공통자원에 접근하는 함수는 synchronized(), 블락시키는 함수는 wait(), 블락을 해제시키는 함수는 notify() 이다.


✅ 문제 2-2. 보기를 참고해 빈칸을 채워주세요.
보기 : Signal and wait, Signal 보내, Signal and continue, 찌릿찌릿찌릿찌릿, 난너를원해
  • ___(a)___ 기법을 사용한 모니터(3) 상황에서, 프로세스P는 프로세스Q가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다.

  • ___(b)___ 기법을 사용한 모니터(3) 상황에서, 프로세스Q는 프로세스P가 모니터를 떠날 때까지 기다리거나 또는 다른 조건을 기다린다.

정답 : a = Signal and wait, b = Signal and continue

두 기법의 절충안으로서, signal()을 호출한 즉시 P가 모니터를 떠나고 Q가 즉시 재개되도록 모니터를 구현할 수 있다.


3. 세마포를 이용한 모니터 구현

✅ 문제 3. 세마포를 이용해 모니터를 구현할 때는 ______ 기법을 사용한다.

힌트 : 문제2-2에 정답이 숨어있어요

정답 : Signal and wait 기법

  1. 각 모니터마다 mutex라는 세마포가 정의되고 그 초기값은 1이다.
  2. 프로세스는 모니터로 들어가기전에 wait(mutex)를 실행하고 모니터를 나온 후에 signal(mutex)를실행 해야 한다.
  3. Signal and wait 기법을 사용해 모니터를 구현한다.
  4. signal()을 호출한 프로세스는 실행 재개되는 프로세스가 모니터를 떠날 때까지 기다려야하므로 next라는 세마포 큐가 추가로 필요하다. signaling 프로세스는 이 next 큐에서 대기한다.
  5. next 세마포 큐에서 일시중지 된 프로세스를 카운트하기위해 next_count 라는 변수를 사용한다.
  6. 이렇게 하면 모니터 안에서의 상호 배제를 보장할 수 있다.

4. Monitor vs Semaphore(보충개념)

  • 세마포는 모니터보다 낮은 수준(혹은 범위)의 개념이다. 세마포를 사용하여 모니터를 구현할 수 있기 때문이다. 세마포는 본질적으로 카운터일 뿐이다. 모니터는 이진 세마포다.
  • 모니터는 공중 화장실과 같다.
    • 한 번에 한 사람 만 입장 할 수 있기 때문이다. 다른 사람이 들어오지 못하도록 문을 잠그고 일을 본 다음 떠날 때 잠금을 해제한다.
  • 세마포는 자전거 대여소와 같다.
    • 자전거 대여소는 정해진 대수의 자전거를 가지고 있다. 자전거를 대여하려고하는데 자전거가 남아있는 경우 자전거를 탈 수 있다. 그렇지 않으면 기다려야한다.
    • 누군가 자전거를 반환하면 그때 다른 사람이 자전거를 탈 수 있다.
    • 자전거를 타던 사람은 자전거를 다른 사람에게 빌려줄 수 있다. 자전거 대여소는 자전거를 돌려받기만 하면 자전거를 반납하는 사람이 누구인지는 신경 쓰지 않기 때문이다.

출처 : [Semaphore vs. Monitors - what's the difference?](