Skip to content

Latest commit

 

History

History
316 lines (246 loc) · 25.1 KB

Critical Section.md

File metadata and controls

316 lines (246 loc) · 25.1 KB

임계구역 문제가 무엇인 지 설명해주세요.

  • 임계구역은 둘 이상의 프로세스에 의해서 동시에 접근하면 안되는 공유 자원(임계자원)에 접근하는 영역(코드 영역)입니다.
  • 즉, 프로그램에서 공유데이터(임계자원)를 이용하는 부분입니다.
  • 이러한 구역에서 공유 자원은 공동으로 이용되기 때문에 프로세스/스레드가 어떤 순서로 어떻게 데이터를 읽거나 쓰느냐에 따라 결과를 예측하기 어렵다는 문제가 있습니다.
  • 임계구역의 예시로는, 다수의 프로세서가 접근 가능한 영역이면서 한 순간에 하나의 프로세서만 사용할 수 있는 영역이 있습니다.

Q) 임계구역 문제를 해결하기 위한 조건을 말해주세요.

  • 세가지 조건을 만족할 때 임계구역 문제를 방지할 수 있습니다.

(1) 상호배제 - 임계영역에는 한번에 하나의 프로세스/스레드만 접근할 수 있습니다.

(2) 진행(progress) - 임계영역에 프로세스가 없다면, 적절한 프로세스를 임계영역에 진입할 수 있게 선택해야 합니다.

(3) 한정 대기(bounded waiting) - 한 프로세스가 임계영역 진입 요청을 한 후 수락되기까지 다른 프로세스가 임계영역에 진입할 수 있는 횟수를 제한해야 합니다. - 이는 다른 프로세스가 영원히 임계영역에 들어가지 못하는 기아 상태를 방지하기 위함입니다.

Q) 임계구역을 해결하기 위한 동기화 기법을 말해주세요.

  • 임계구역 문제를 해결하기 위해선 한번에 하나의 프로세스만 임계구역을 이용하게끔 보장해야 합니다. 임계 영역의 동시접근을 해결하기 위한 방법으로 OS supported SW Solutions 인 Spinlock, Semaphore, Monitor기법이 존재합니다.

(1) Spinlock

  • 두 스레드가 하나의 임계영역에 접근할때, 하나만 접근 가능한 상황에서 Thread 0이 임계영역을 점유중이고 lock을 걸어놓은 상태일때, Thread 1은 접근이 불가능하고 기다려야 합니다.

  • spinlock에서는 기다리는 과정에서 Busy waiting이라는 방법을 사용하는데, Thread 0이 임계영역을 다 사용했는지의 여부를 Thread 1이 계속 확인하는 것입니다.

  • Busy waiting은 컴퓨터 리소스가 크게 낭비된다는 단점이 있습니다.

  • CPU가 여러개인 환경(멀티 프로세서)에서만 사용 가능합니다. 싱글 코어에서 스핀락은 사용하지 못합니다. (CPU가 하나면 Busy-waiting 하나밖에 못하기 때문입니다.)

  • Spin Lock의 개발 컨셉은 "lock - unlock 사이에 약간의 시간만 기다리면 바로 lock이 풀리는데 굳이 context switch를 해서 overhead를 발생시킬 필요가 있을까"에서 출발했습니다.

  • "lock - unlock"과정이 아주 짧을 때 유용합니다. context switch하는 시간보다 lock의 주기가 더 짧으면 Spin Lock을 사용합니다.

  • 하지만 Critical Section이 매우 크거나 프로세스의 처리 속도가 느리다면 Spin Lock은 대기하고 있는 프로세스들이 CPU에 주는 부담이 굉장히 커집니다.

image

(2) Mutex

  • Mutual Exclusion 의 줄임말로 상호 배제를 가능하게 합니다.

  • 뮤텍스는 lock이기에 실행할때 잠궜다가 다 쓰고나면 열어둔 후, 대기하던 다음 프로세스를 깨워주며 Busy waiting단점을 보완합니다.

  • 주의점으로는 잘못 설계할 경우 lock 권한을 가진 스레드가 항상 점유해버리므로 starvation 문제가 일어날 수 있습니다.

  • 많은 lock을 사용하게 될 경우, deadlock 발생가능성이 높습니다.

  • <작동원리> - 1. 프로세스가 Critical Section에 들어가려면 먼저 "Lock"을 획득합니다. : acquire() - 2. Critical Section에서 빠져나올 때는 "Lock"을 반환해야 합니다. : release() => acquire() & release()는 둘 다 "Atomic"하게 동작합니다.

  • 추가적으로, 뮤텍스가 스핀락보다 항상 좋다고 말할 수 없습니다. - 1. 멀티코어 환경이며 (스핀락은 싱글코어에선 작동할 수 없습니다.) - 2. 임계구역에서의 작업이 컨텍스트 스위칭보다 더 빨리 끝난다면 오히려 스핀락이 더 유리합니다.

"Busy Waiting" vs "Block & WakeUp"

  • 일반적인 경우에는 Block & WakUp이 더 효율적입니다.
  • Block & WakUp 장점
      1. 쓸데없이 CPU를 점유하면서 기다리지 않습니다.
      1. 먼저 Resoruce 여부를 확인하고 여분이 없으면 알아서 CPU 반납하고 block합니다.
      1. 전체적으로 CPU 처리율이 향상됩니다.
  • Block & WakUp 단점
      1. overhead
    • Block은 ready -> block 과정이고 WakeUp은 block -> ready 과정이고 이 때 당연히 overhead가 발생

1) Critical Section이 매우 짧은 경우 - Block & WakeUp의 overhead가 "Busy Waiting"의 CPU 점유보다 좋지 않습니다. => Spin Lock을 선택합니다.

2) Critical Section이 긴 경우 - "Busy Waiting"은 결국 CPU를 점유하고 CPU를 생산적으로 활용하지 않기 때문에 CPU의 낭비가 심합니다. 따라서 Critical Section이 긴 경우 "Block & WakeUp"을 통해서 CPU의 처리율을 향상시키는 것이 더 좋습니다. => Mutex, Semaphore을 선택합니다.

(3) Semaphore

  • 세마포어는 spinlock의 단점인 busy waiting을 극복하기 위해 wait()와 signal() 메소드를 활용합니다.
  • Wait 상태인 스레드는 대기 큐에 들어가서 기다리며 while 문을 반복 실행하지 않으므로 리소스 낭비가 없습니다.
  • 임계영역을 점유중이던 스레드는 작업이 끝나는대로 signal()을 통해 lock을 반환하므로써 대기 큐에 존재하던 스레드를 깨워 준비 큐로 이동시킵니다.

image

  • 크게 binary semaphore와 counting semaphore 두가지로 구분됩니다.

    • (3-1) Binary semaphore
      • S가 0 과 1 두가지의 값만 존재합니다.
      • 하나의 임계영역은 하나의 스레드만이 점유 가능합니다.
    • (3-2) Counting semaphore
      • S가 양의 정수라서 해당 정수 값만큼의 스레드들이 동시에 접근 가능합니다.
      • Counting Semaphore에서의 S는 "Available한 Resource의 수"입니다.
      • 따라서 여러 스레드에 접근 기회를 제공합니다.
  • 세마포어와 스핀락 비교 <리소스의 낭비 비교>

    • spinlock은 loop를 통해 스레드로 하여금 끊임없이 임계영역의 사용 가능 여부를 확인하도록 강제합니다
    • 반면, semaphore는 바로 접근이 불가능한 스레드는 sleep 시키고 사용가능한 상황일때 awaken up 시켜줍니다. => semaphore에서는 리소스의 낭비를 줄일 수 있습니다

    <lock 구현과 대기 시간 비교>

    • 그러나 spinlock은 구현이 간단하며 lock을 짧은 시간동안만 점유할 경우 에는 오히려 좋습니다.
    • semaphore는 구현이 어렵지만 오랜 시간을 대기해야하는 상황에서 효율적입니다.

(4) Monitor (JAVA - synchronized)

  • 스레드가 상호 배제와 협동성을 가질 수 있도록 하는 동기화 메커니즘입니다.

  • 스레드가 어떻게 자원에 접근하는지 감시합니다.

  • Java 에서는 Synchronized 키워드를 사용해 Monitor를 구현합니다.

  • 모니터는 entry set, wait set, 임계영역 이렇게 세부분으로 구분됩니다.

  • 임계영역은 synchronized 키워드가 선언된 부분으로 스레드가 접근하고 싶은 영역입니다. - wait set은 스레드가 대기하는 곳입니다. - entry set은 스레드가 입장하는 곳입니다. - wait() , notify() 메소드를 사용합니다.

  • 작동 원리

      1. 스레드가 entry set에 들어가서 스케줄러를 기다립니다.
      1. 스케줄러가 스레드를 임계영역에 들여보내줍니다.
      1. 작업이 완료될 수도 있지만 때로는 wait set에서 대기를 해야합니다.
      1. 다시 차례가 오면 임계영역에 접근하여 작업을 완료합니다.
    • JVM의 스케줄러는 우선순위를 기반으로 한 스케줄링 알고리즘을 사용합니다.
    • 동일한 우선순위를 가진 경우에는 FIFO 스케줄링으로 해결합니다.

    Q-1) 세마포어는 여러개의 프로세스, 스레드를 허용하는데 이 방식과 용어에 대해 말해주세요.

    • 세마포어는 세마포어 값의 범위에 따라서 계수 세마포어(Counting Semaphore)와 이진 세마포어(Binary Semaphore)로 구분됩니다.
    • 생산자-소비자 문제를 해결하기 위해 사용돠며 S가 0이상의 정수 값을 갖습니다.
    • 여러 프로세스, 여러 스레드의 접근을 허용하는 것은 계수 세마포어라고 지칭합니다.

    Q-1-1) Binary Semaphore란?

    • Binary Semaphore는 세마포어에서 사용하는 변수가 0혹은 1인 세마포어입니다. 이는 한 임계 구역에 하나의 프로세스 / 하나의 스레드만 접근을 허용합니다.
    • 상호배제나 프로세스 동기화의 목적으로 사용,2 S가 0과 1 두 값만 갖습니다.

    Q-2) 이진 세마포어와 뮤텍스는 같은 것이라고 볼 수 있나요?

    • 둘은 명확한 차이가 존재합니다.
    • (1) lock을 해제할 수 있는 권한의 차이가 있습니다. 뮤텍스는 무조건 lock을 건 주체만 lock을 해제할 수 있습니다. 반면 세마포어는 lock을 걸지 않은 주체도 lock을 해제할 수 있습니다.
    • (2) mutex는 priority inheritance 특성을 사용하나, 세마포어는 사용하지 않습니다. - priority inheritance : lock을 획득한 프로세스/스레드의 우선순위를 높여주는 것입니다. - mutex는 lock을 획득할 수 있는 존재를 예측할 수 있어, 이 속성을 사용가능하나, 세마포어는 예측이 어려워 이를 사용하지 않습니다.
    • (3) binary semaphoresignaling mechanism 이고 mutexlocking mechanism이라는 차이가 존재합니다.

    (+) 세마포어가 해결해주는 문제

      1. 상호배제 문제
      • spinlock은 물건이 없으면 Busy waiting을 했으나, 세마포어는 대기실(ready queue)에서 기다리게 하고 lock을 얻을 기회가 오면 이를 할당해주면서 상호배제 문제를 해결합니다.
      1. 프로세스 동기화 프로세스들의 실행 순서를 맞춰줍니다.

Q) IPC의 여러가지 통신 중 가장 기억에 남는 것을 말해주세요. (Process part)

  • PIPE

    • PIPE를 통해서 동일한 PPID를 가진 프로세스들 간에 단방향 통신을 지원합니다.
    • 단방향 연결을 수행합니다.
    • 익명 파이프(부모 자식 프로세스간 통신 할때 사용) 와 Named Pipe(연관이 전혀 없는 프로세스간에 통신)가 존재합니다. image image
  • Message Queue

    • 메모리를 사용한 PIPE이며 구조체 기반으로 통신을 한다.
    • 메세지 큐는 커널에 저장되는 Linked List 형태입니다. 커널에서 제공하는 Message queue 이기 때문에 EnQueue 하는데 제한이 존재합니다.
    • msgtype에 따라 다른 구조체를 가져올 수 있습니다. image
  • Shared Memory - 시스템 상의 공유 메모리를 통해 통신합니다. - 일정한 크기의 메모리를 프로세스간에 공유하는 구조이며 공유 메모리는 커널에서 관리됩니다. image - IPC through Shared memory 를 통해 여러 프로세스가 하나의 메모리를 공유할 수 있습니다. - 이는 pipe, message queue 방식과 달리 매개체를 경유하지 않기에 IPC 기법 중 가장 빠릅니다. - 즉 메모리 자체를 공유하기에 불필요한 데이터 복사의 오버헤드가 발생하지 않는다는 장점이 있습니다. - 생성된 공유메모리는 커널에 의해 관리됩니다. - 같은 메모리 영역을 여러 프로세스가 공유하기에 적절한 동기화가 필요하다는 점이 존재합니다.

    Q-1) 소켓 통신에 대해 설명해주세요.

    • 소켓 : 네트워크 소켓은 컴퓨터 네트워크를 경유하는 프로세스 간 통신의 종착점을 가리킵니다. 즉, 프로그램이 네트워크에서 데이터를 통신할 수 있도록 연결해주는 역할을 수행합니다.

Q) 동기화를 위한 하드웨어 명령어 2가지를 말해주세요.

  • 하드웨어 명령어로는, test_and_set() & compare_and_swap() 이 존재합니다.
  • 많은 기계들은 한 워드(word)의 내용을 검사하고 변경하거나, 두 워드의 내용을 원자적으로(atomically) 교환(swap)할 수 있는, 즉 인터럽트 되지 않는 하나의 단위로서, 특별한 하드웨어 명령어들을 제공합니다.
  • 이와 같은 하드웨어 명령어들을 통해 임계구역 문제를 해결할 수 있습니다.
  • HW 명령어는 데이터의 접근 → 연산 → 연산 결과 저장 의 과정을 한 번에 수행할 수 있는(ATOMIC 실행,원자적 실행) HW 지원을 해줌으로써 실행 중 인터럽트를 받지 않아서 preemption 되지 않습니다. => 즉, 원자적으로 수행한다는 것은 인터럽트 되지 않고 수행된다는 것입니다.

(1) test_and_set()

  • test_and_set(lock) 명령어는 lock의 값을 읽고(복사 후 반환), lock을 True로 설정하는 일을 한 번에(원자적으로) 수행합니다.

(2) compare_and_swap()

  • 마찬가지로 원자적으로 특정한 연산을 수행해줍니다. test_and_set 과는 다르게 3개의 매개 변수를 사용합니다. value가 expected와 같다면, value의 값을 new_value로 설정하는 일을 한 번에 수행하며 결과적으로 본다면 test_and_set과 동일하게 작동합니다.

(3)원자적 변수 (Atomic Variables)

  • 원자적 변수는 compare_and_swap 명령어를 다시 원자적인 연산으로 구현하여 사용하는 도구입니다.

(+) 소프트웨어적 해결 방식의 문제점 (HW 명령어 존재 이유)

  • 속도가 느립니다.
  • 구현이 복잡합니다. (<-> HW 명령어는 구현이 간단합니다.)
  • 상호배제 실행 중 preemption 문제가 있습니다. (<-> HW는 ATOMICALLY 실행 지원을 해줌으로써 실행 중 인터럽트를 받지 않기에, preemption 되지 않습니다.)

(+) SW적 해결방식은 무엇인가요?

  • Peterson’s Solution이 존재합니다.

  • 이는 임계 구역과 나머지 구역을 번갈아 가며 실행하는 두 개의 프로세스가 있는 경우로 한정해서 생각합니다.

  • 두 프로세스가 두 개의 데이터 항목을 공유하여 공유메모리를 통해 문제를 해결합니다.

  • flag와 turn 변수를 사용하여 프로세스가 임계구역에 들어가려고 하는 것을 구분합니다.

    • flag 값이 true 이면 프로세스가 임계구역에 들어가려고 하는 것을 나타냅니다.
  • 이 알고리즘은 임계구역 문제 해결의 3가지 조건을 모두 만족합니다.

  • 다만, 고전적인 소프트웨어 기반의 해결책이기에, 현대의 컴퓨터 아키텍처에서 작동하지 않을 수도 있습니다.

    Q-1) test&set 진행 시 Polling을 계속하며 상태를 계속해서 확인하는 용어를 뭐라고 하나요?

    • busy waiting입니다. 다만 이는 CPU를 효율적으로 사용하지 못한다는 단점을 가집니다.
    • busy waiting은 "Multiprogramming System"에서 다른 프로세스가 CPU를 할당받으면 생산적으로 사용할 수 있는 것을 "Busy Waiting"에서 의미없이 CPU 주기를 낭비합니다.

Q) 임계영역 문제 방지 조건 중 "상호배제" 조건을 만족하기 위해 interrupt를 사용하는 것이 가능할까요?

  • 단일 프로세스 시스템 환경이라면, 가능합니다.
  • 장점으로는 구현이 단순하며 & 인터럽트가 발생하지 않으면 코드가 실행 중에 다른 쓰레드가 중간에 끼어들지 않는다는 것을 보장할 수 있습니다.
  • 단점으로는 단일 프로세스 시스템에서만 가능하고, 멀티 프로세스 시스템에서는 불가하다는 점입니다.
    • 이유는 여러 쓰레드가 여러 CPU에서 실행 중이라면 각 쓰레드가 동일한 임계 영역을 진입하려고 시도할 수 있습니다. 그러나 이때에 특정 프로세서에서의 인터럽트 비활성화는 다른 프로세서에서 실행 중인 프로그램에는 전혀 영향을 주지 않기에 멀티 프로세스 시스템에서는 단순 interrupt로 상호배제를 예방할 수 없습니다.

Q) 임계구역 조건이 지켜지지 않으면 발생하는 문제를 말해주세요.

  • 데이터 정합성 문제가 발생합니다. 예시로 계좌 출입금 문제가 있습니다.

    Q-1) 두 개 이상의 프로세스, 스레드가 공유 자원에 접근해서 일어나는 문제 상황에 대한 용어를 말해주세요.

    • race condition입니다.
    • race condition 은 2개 이상의 프로세스가 공유 자원을 병행적으로 읽거나 쓰는 상황인 경쟁 조건을 의미합니다.
    • 여러 프로세서가 동시에 접근하면 시간차로 예상치 못한 결과를 만들 수 있는 것과 같이 실행순서에 따라 결과값이 달라지는 현상에서 발생합니다.

    Q-2) race condition을 방지하기 위한 방법을 말해주세요.

    • SW 솔루션 (피터슨 알고리즘), HW 솔루션 (test&set , compare&swap 명령어), OS 지원 SW 솔루션 (Spin-Lock, Mutex, Semaphore) 이 있습니다.

Q) JAVA, Spring 에서 데이터 정합성 문제가 발생했던 경험과, 있다면 해결 경험도 말해주세요.

  • PostgreSQL을 사용했는데, PostgreSQL은 동시성 이슈를 방지해주는 역할을 가지고 있어 경험은 없습니다.

    Q-1) 동시성 문제와 데이터 정합성 문제의 차이를 말해주세요.

    • 동시성 문제

      • 동일한 자원에 대해 여러 스레드가 동시에 접근 하면서 발생하는 문제입니다.
    • 데이터 정합성 문제 :

      • 데이터가 서로 모순 없이 일관되게 일치하는 상태입니다.
    • (+) JAVA, Spring 에서 동시성 문제/정합성 문제가 일어나면 해결하는 방식으로는, - LOCK (비관적 락, 낙관적 락)을 걸어줍니다. - synchronized 어노테이션을 통해 LOCK을 걸어줍니다.

    Q-2) 트랜잭션과 더불어서 데이터 정합성 문제에 대해 설명해주세요. (DB part)

    • 트랜잭션

      • 데이터베이스의 상태를 변화시키기 해서 수행하는 작업의 단위입니다.
    • 트랜잭션의 특징 (ACID)

      • Atomic (원자성)
        • 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것입니다.
      • Consistency (일관성)
        • 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것입니다.
      • Isolation (독립성)
        • 어떤 트랜잭션이든, 다른 트랜잭션의 연산에 끼어들 수 없습니다.
      • Duration (지속성)
        • 트랜잭션이 성공적으로 완료됬을 경우, 결과는 영구적으로 반영되어야 한다는 것입니다.
    • 트랜잭션의 Commit, Rollback

      • COMMIT

        • Commit이란 하나의 트랜잭션이 성공적으로 끝났고, 데이터베이스가 일관성있는 상태에 있을 때, 하나의 트랜잭션이 끝났다라는 것을 가리킵니다.
      • ROLLBACK

        • 하나의 트랜잭션 처리가 비정상적으로 종료되어 트랜잭션의 원자성이 깨진경우, 트랜잭션을 처음부터 다시 시작하거나, 트랜잭션의 부분적으로만 연산된 결과를 다시 취소시킵니다.
    • 트랜잭션 격리 수준(isolation level)에 따른 데이터 정합성 문제

      • 데이터 정합성이란?

        • 데이터가 서로 모순 없이 일관되게 일치하는 상태입니다.
      • 트랜잭션 격리 수준이란?

        • 동시에 여러 트랜잭션이 처리될 때, 트랜잭션끼리 얼마나 서로 고립되어 있는지를 나타내는 것입니다.
        • (4)를 제외한 (1),(2),(3) 레벨 수준의 낮은 격리 수준에서는 아래와 같은 데이터 정합성 문제가 일어날 수 있습니다.

        (1) Read Uncommitted - Dirty Read 어떤 트랜잭션에서 아직 실행이 끝나지 않은 다른 트랜잭션에 의한 변경사항을 보게되는 경우를 가리킵니다. 커밋되지 않은 수정중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상입니다.

        (2) Read Committed - Non-Repeatable Read 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때 그 사이에 다른 트랜잭션 값을 수정 또는 삭제하면서 두 쿼리의 결과가 상이하게 나타나는 일관성이 깨진 현상을 가리킵니다. 한 트랜잭션에서 똑같은 SELECT를 수행했을 때 항상 같은 결과를 반환해야 한다는 Repeatable Read 정합성에 어긋나는 현상입니다.

        (3) Repeatable Read - Phantom Read - 한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상입니다. - 트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타납니다.

        (4) Serializable (정합성 문제 발발 X) - 트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층입니다. - 가장 엄격한 격리 수준으로 완벽한 읽기 일관성 모드를 제공합니다. - 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 및 입력이 불가합니다.

Q) Thread-safe에 대해 어떤 의미인지 설명해주세요.

  • 두 개 이상의 프로세스 / 스레드가 하나의 임계구역에 들어가서 객체에 동시에 접근하더라도 결과의 정합성을 보장하는 것이 가능한 것입니다.

    Q-1) Thread-safe를 구현할 수 있는 방법에 대해 설명해주세요.

    • 동기화 처리를 적절히 해주면 됩니다.
    • JAVA 에서 주로 사용하는 동기화 기법은 아래와 같습니다.
    • (1) java.util.concurrent 제공해주는 동시성 보장 라이브러리 사용합니다.
    • (2) Singleton 패턴을 도입합니다.
    • (3) @synchronized 를 통해 동시성 관리를 해줍니다.

    Q-2) 재진입성 (Reenterant) 개념에 대해 설명해주세요.

    • 재진입성이라는 의미로, 어떤 함수가 Reentrant하다는 것은, 여러 스레드가 동시에 접근해도 언제나 같은 실행 결과를 보장한다는 의미를 가집니다.
    • 이를 만족하기 위해서 해당 서브루틴에서는 공유자원을 사용하지 않으면 됩니다.
    • 즉, 정적(전역) 변수를 사용하거나 반환하면 안 되고 호출 시 제공된 매개변수만으로 동작해야 합니다.
    • 멀티태스킹 환경에서는 재진입 함수를 사용해야 합니다.
      • 재진입성을 갖추지 못한 함수는 멀티 쓰레드에서 사용할 수 없습니다.
      • 재진입성은 주로 전역번수를 안쓰고 로컬 변수를 사용함으로써 실현 가능합니다.

사진, 내용에 대한 출처

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=dong5053&logNo=220717508763 https://mommoo.tistory.com/62 https://dar0m.tistory.com/225 https://luv-n-interest.tistory.com/465 https://doitnow-man.tistory.com/110 https://velog.io/@hahahaa8642/OS-Spinlock-Semaphore-Mutex-Monitor https://cs-ssupport.tistory.com/m/428