운영체제

16. 동기화(스핀락, 세마포어, 뮤텍스)

ggomjiu 2025. 2. 10. 11:38

데이터 접근

- 데이터가 저장되어 있는 위취로부터 데이터를 읽어와서 연산한 뒤, 연산한 결과를 이전에 저장되어 있던 그 위치에 다시 저장

- 데이터를 읽기만 하면 문제가 없는데, 데이터를 연산하고 수정하게 되면 누가 먼저 읽어 갔는지에 따라 결과가 달라질 수 있음

-> 이때 동기화(Synchronization) 문제 발생

 

프로세스 동기화(Process Synchronization)

: 여러 프로세스 / 스레드를 동시에 실행해도 공유 데이터의 일관성을 유지하는것

- 공유 데이터의 동시 접근은 데이터의 불일치 문제를 발생시킬 수 있음

- 일관성(Consistency)유지를 위해서는 협력 프로세스 간의 실행 순서를 정해주는 메커니즘이 필요

 

경쟁 상태(Race Condition)

: 여러 프로세스 / 스레드가 동시에 같은 데이터를 조작할 때 타이밍이나 접근 순서에 따라 결과가 달라질 수 있는 상황

- 이것을 막기 위해 Current Process는 동기화되어야 함

- Storage-box를 공유하는 Execution-box가 여러 개 있는 경우 race condition 가능성이 있음

-> count++ 연산이 실행되는 동안 연산 이전 데이터를 읽어간 count--에서 연산을 마치고 저장하면 count-- 연산만 적용됨

 

1. OS에서 Race Condition이 발생할 때

1) Kernel 수행 중 인터럽트 발생

- 커널 모드 running 중 count++하고 있음

- CPU 레지스터로 데이터를 읽어온 상황에서

- 인터럽트가 들어오면 처리 루틴이 수행되며 count--를 반영

- 다시 count++이 실행되는데 이미 읽어오는 작업은 끝났기 때문에 count++ 후 저장

-> running 중에 작업이 끝날 때까지는 disable interrupt 상태로 해서 작업이 끝나기 전까지는 인터럽트가 실행되지 않도록 함

 

2) Process가 System Call을 하여 Kernel Mode로 수행 중인데 Context Switch가 일어나는 경우

- 커널 모드에서 수행 중일 때는 CPU를 Preempt하지 않음

-> 커널 모드에서 유저 모드로 돌아갈 때 함

- CPU 할당 시간에 편차가 생길 수 있음

 

3) Multiprocessor에서 Shared Memory내의 Kernel Date에 접근할 때

방법1)

- 한 번에 하나의 CPU만이 커널에 들어갈 수 있도록 하고, 하나의 커널을 LOCK으로 막고 커널을 빠져나올 때 UNLOCK

-> 커널 전체를 LOCK하기 때문에 비효율적

 

방법2)

- 커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대한 LOCK / UNLOCK

 

임계 영역(Critical Section)

: 공유 데이터의 일관성을 보장하기 위해 하나의 프로세스 / 스레드만 진입해서 실행가능한 영역

 

1. Problem

- 하나의 프로세스가 임계 영역에 있을 때 다른 모든 프로세스는 임계 영역에 들어갈 수 없어야 함

 

2. Problem을 해결하기 위한 조건

- Multual Exclusion(상호 배제)

  • 한 번에 하나의 프로세스 / 스레드가 임계 영역에서 실행할 수 있음

- Progress(진행)

  • 아무도 임계 영역에 있지 않으면 들어가고자 하는 프로세스가 있으면 임계 영역에 들어가게 해줘야 함

- Bounded Waiting(한정된 대기)

  • 하나의 프로세스 / 스레드가 임계 영역에 들어가기 위해서는 무한정 기다리는 상황이 되면 안됨
  • 다른 프로세스들의 기아(Starvation)을 막기 위해서

 

3. Solution

- Mutual Exclusion 보장 -> LOCK 사용

 

1) 스핀 락(Spinlock)

: lock을 가질 수 있을 때까지 반복해서 시도

- 임계 영역이 lock이 걸려서 진입이 불가능할 때, 임계 영역이 unlock되어 진입이 가능해질 때까지 루프를 돌면서 재시도하여 스레드가 CPU를 점유하고 있는 상태

- 단점

  • 기다리는 동안 CPU 낭비
  • Busy-Waiting 상태

2) 뮤텍스(Mutex)

: 여러 스레드를 실행하는 환경에서 자원에 대한 접근에 제한을 강제하기 위한 동기화 메커니즘

- lock을 가질 수 있을 때까지 휴식

- Mutual Exclusion의 약자

- 스핀락과 차이점

  • 스핀락이 임계 영역이 unlock되어 권한을 획득하기까지 Busy-waiting 상태를 유지한다면
  • 뮤텍스는 Block(Sleep) 상태로 들어갔다가 Wakeup이 되면 다시 권한 획득을 시도
  • Block-wakeup 상태 : 뮤텍스 lock은 내부적으로 value로 컨트롤하는데 value를 가질 수 없을 때는 큐에서 Block하면서 기다림 -> CPU 사이클을 불필요하게 낭비하는 것을 최소화시켜줌
  • value : 서로 취득하려고 하는 공유 데이터
  • guard : race condition 발생을 막기 위해 지켜주는 장치
  • 멀티 코어 환경이고, 임계 영여게서의 작업이 Context Switching보다 더 빨리 끝난다면 스핀락이 뮤텍스보다 더 이점을 가짐

3) 세마포어(Semaphore)

: 멀티프로그래밍 환경에서 다수의 프로세스나 세레드의 여러 개의 공유 자원에 대한 접근을 제한하는 방법으로 사용됨

- Signal Mechanism을 가진 하나 이상의 프로세스 / 스레드가 임계 영역에 접근이 가능하도록 하는 장치

- 목적 : Mutual Exclusion이 아닌 공유 자원에 대한 관리

  • 스핀락과 뮤텍스와 달리 표현형이 정수형 -> 이점을 살려 하나 이상의 컴포너느가 공유 자원에 접근할 수 있도록 허
  • 컴포넌트가 특정 자원에 접근할 때 wait이 먼저 호출되어 임계 영역에 들어갈 수 있는지 먼저 확인
  • 임계 영역에 접근이 가능하다면 wait을 빠져나와 임계영역에 들어가고, 이후 signal이 호출되어 임계 영역에서 빠져나옴
  • 세마포어는 순서를 정해줄 때 사용
  • 세마포어는 Signaling 메커니즘으로 락을 걸지 않은 스레드도 signal을 통해 락을 해제할 수 있음