데이터를 읽어와서 연산을 해서 저장하는 방식에서는 프로세스 동기화 문제가 발생!
S-box를 공유하는 E-box가 여럿 있는 경우 Race Condition의 가능성이 있음
Race condition이 발생할 수 있는 상황
유저레벨보다 커널모드에서 문제 발생 시, 문제가 더 심각함
kernel 수행 중 인터럽트 발생 시
Process가 system call을 하여 kernel mode로 수행 중인데 context switch가 일어나는 경우
Multiprocessor에서 shared memory내의 kernel data
커널모드 running 중 interrupt가 발생하여 인터럽트 처리루틴이 수행
➡️ 양쪽 다 커널 코드이므로 kernel address space 공유
위 그림에선 interrupt handler의 count--
가 동작하지 않고 count++
만 처리된 결과 값이 저장됨
해결방법으로 커널과 관련된 작업이 수행중일 땐, interrupt가 들어와도 수행시키지 않고 그 작업이 끝난 후에 수행하도록 해결함
커널 코드 실행중에서(카운트 값 증가) 프로세스 B로 넘어간 상황
프로세스 B에서 요청한
count++
이 반영되지 않고 A에서 요청한count++
만 반영됨
해결방법: 커널 모드에서 수행 중일 때는 CPU를 preempt하지 않고, 커널 모드에서 사용자 모드로 돌아갈 때 preempt
해결책
한번에 하나의 CPU만이 커널에 들어갈 수 있게 하는 방법
커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대한 lock / unlock을 하는 방법
공유 데이터(shared data)의 동시 접근(concurrent access)은 데이터의 불일치 문제(inconsistency)를 발생시킬 수 있다.
일관성(consistency) 유지를 위해서는 협력 프로세스(cooperating process)간의 실행 순서(orderly execution)를 정해주는 메커니즘 필요
Race condition
race condition을 막기 위해서는 concurrent process는 동기화 (synchronize)되어야 한다
n 개의 프로세스가 공유 데이터를 동시에 사용하기를 원하는 경우, 각 프로세스의 code segment
에는 공유 데이터를 접근하는 코드인 critical section
이 존재
Problem
Mutual Exclusion(상호배제)
Progress(진행)
Bounded Waiting(유한 대기)
가정
- 모든 프로세스의 수행 속도는 0보다 크다
- 프로세스들 간의 상대적인 수행 속도는 가정하지 않는다
위 그림에서 turn은 critical section에 들어갈 차례를 나타내는 변수
그러나 위 코드는 progress 조건이 만족하지 않음
둘다 flag가 true인 상황에선 아무도 critical section에 접근할 수 없음
mutual exclusion는 만족하지만 progress 조건을 만족하지 않음
모든 조건 만족
그러나 Busy Waiting문제(=spin lock)를 가지고 있음(계속 CPU와 memory를 쓰면서 wait)
하드웨어적으로 Test & modify를 atomic하게 수행할 수 있도록 지원하는 경우 앞의 문제는 간단히 해결
앞의 방식들을 추상화시킴
P연산은 CPU 자원을 획득하는 과정 V연산은 반납하는 과정
하지만 이 방식은 busy-wait이며, 이는 효율적이지 못함(=spin lock)
➡️ Block & Wakeup 방식의 구현(=sleep lock)
block과 wakeup을 다음과 같이 가짐
block
커널은 block을 호출한 프로세스를 suspend 시킴
이 프로세스의 PCB를 semaphore에 대한 wait queue에 넣음
wakeup(P)
block된 프로세스 P를 wakeup시킴
이 프로세스의 PCB를 ready queue로 옮김
S 값이 음수이면 누군가가 자원을 기다리고 있다는 의미 -> wakeup 시켜주어야함
Block/wakeup overhead v.s. Critical section 길이
Deadlock: 둘 이상의 프로세스가 서로 상대방에 의해 충족될 수 있는 event를 무한히 기다리는 현상
각 프로세스가 얻어야하는 자원이 다른경우 (S와 Q) 0번 프로세스에서는 S를 얻고, 1번 프로세스에선 Q를 얻었을 때, 데드락이 발생할 수 있음
➡️ 이런 경우 각 프로세스마다 얻어야하는 자원의 순서를 맞추어 줌으로써 해결할 수 있음
Starvation
indefinte blocking
. 프로세스가 suspend된 이유에 해당하는 세마포어 큐에서 빠져나갈 수 없는 현상Shared data
→ buffer 자체 및 buffer 조작 변수(empty/full buffer의 시작 위치)
Synchronization variables
한 process가 DB에 write 중일 때 다른 process가 접근하면 안됨
read는 동시에 여럿이 해도 됨
해결책
shared data
Synchronization variables
starvation 발생이 가능(writer가 계속 기다릴 가능성 있음)
이 solution의 문제점
해결 방안
두 번째 해결방안을 코드로 구현한 결과
약간의 세마포어의 철학과는 잘 맞지 않음 → 세마포어는 기본값을 특정 값으로 준다음 그것을 낮추면서 사용하는 것인데 여기선 초기 값을 0으로 두고 시작
Semaphore의 문제점
모니터란 동시 수행중인 프로세스 사이에서 abstract data type의 안전한 공유를 보장하기 위한 high-level synchronization construct
아래 그림은 모니터 구조
condition x,y;
세마포어 변수처럼 비슷한 역할을 해주는 것이
condition variable
Condition variable
은 wait
와 signal
연산에 의해서만 접근 가능
→ x.wait()
x.wait()
을 invoke한 프로세스는 다른 프로세스가 x.signal()
을 invoke하기 전까지 suspend된다.
x.signal()
x.signal()
은 정확하게 하나의 suspend된 프로세스를 resume한다. Suspend된 프로세스가 없으면 아무 일도 일어나지 않는다.
모니터 코드가 더 추상화 되어 있어서 세마포어보다 훨씬 이해하기 쉬움!