1. Background
์ด ์ฅ์์๋ ํ๋ก์ธ์ค๊ฐ ๋ณํ ๋๋ ๋ณ๋ ฌ๋ก ์คํ๋ ๋ ์ฌ๋ฌ ํ๋ก์ธ์ค๊ฐ ๊ณต์ ํ๋ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ ์ด๋ค ๋ฌธ์ ๋ฅผ ์ผ์ผํค๋ ์ง์ ๊ดํด ์ค๋ช ํ๋ค.
Process communication method ์ธ 1)message passing 2)Shared memory๊ฐ ์ด๋ฃจ์ด ์ง๋ ์ถฉ๋์ด ์ผ์ด๋ ์ ์๋ค.
์) Producer-consumer problem
- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ(shared memory)๋ฅผ ์ฌ์ฉํ ๋ Producer์ Consumer์ ๊ณผ์ ์ด ์ด๋ฃจ์ด ์ง๋ฉด์ Buffer๊ฐ ์ด์ฉ๋๋๋ฐ ์ด๋ ์ถฉ๋์ด ๋ฐ์ํ ์ ์๋ค.
: Concurrent Access of Shared Data(๊ณต์ ๋ฐ์ดํฐ๋ก์ ๋์์ ๊ทผ)
์์ธํ๊ฒ ์ค๋ช ์ ํ์๋ฉด, size๊ฐ 5์ธ buffer(circular queue)๊ฐ ์๋ค๊ณ ํ ๋, Producer๋ counter๋ฅผ 1์ฉ ์ฆ๊ฐ์ํค๊ณ , Consumer๋ counter๋ฅผ 1์ฉ ๊ฐ์์ํจ๋ค. ์๋ producer์ consumer๋ ์ด๋ฅผ ๊ตฌํํ ์ฝ๋์ด๋ค.
Producer
//Producer While(true){ while(counter == BUFFER_SIZE); //true = ๋ฒํผ๊ฐ ๊ฝ์ฐธ / false = ๋ฒํผ ๊ณต๊ฐ ์์, ๋ค์์ค๋ก buffer[in] = nextProduced; in = (in + 1) % BUFFERSIZE; counter++; }
producer๋ buffer์ ์ฅ์์ ์์๋๊ธฐ๋ก buffer์ ์ฑ์ธ ์ ์๋ ๊ณต๊ฐ์ด ์๋ค๋ฉด(๋ฒํผ๊ฐ ๋น์ด์๋ค๋ฉด) ๋ฒํผ๋ฅผ ์ฑ์ฐ๊ณ counter๋ฅผ ์ฆ๊ฐ์ํค๋ ์ญํ ์ ํ๋ค.
Consumer
//Consemer while(true){ while(counter == 0);//true = ๋ฒํผ ๋น / false = ๋ฒํผ ๋น์ด์์ง ์์ nextConsumed = buffer[out]; out = (out + 1) % BUFFER_SIZE; counter--; }
consumer๋ producer์ ์์ ํ ๋ฐ๋๋ก ๋์๊ฐ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
ํ์ง๋ง ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค!
- Synchronization Problem
๋จผ์ producer๊ฐ ๋จผ์ ์คํ๋ ์ํ์์๋ถํฐ ์ํฉ์ ์ดํด๋ณด์.
๊ทธ ์ ์ counter๋ผ๋ ๋ณ์์ ๊ฐ์ด ์ด๋ค ๊ณผ์ ์ ๊ฑฐ์ณ ์ฆ๊ฐํ๊ณ ๊ฐ์ํ๋ ์ง ๊ฐ๋ตํ ๋ณด์.
- counter++์ ๊ณผ์
//counter์ ๊ฐ์ด ๋ ์ง์คํฐ์ ์ ์ฅ๋๊ณ ์ฆ๊ฐ๋ ๋ ์ง์คํฐ์ ๊ฐ์ counter์ ๋ค์ ์ ์ฅ์ํค๋ ๊ณผ์ ์ผ๋ก ์งํ๋๋ค. register_1 = counter register_1 = register_1 + 1 counter = register_1
- counter--์ ๊ณผ์
register_2 = counter register_2 = register_1 - 1 counter = register_2
[Normal situation]
- counter์ ๊ธฐ์กด ๊ฐ์ 5
- producer์ consumer๊ฐ ๋์์ ๊ฐ์ ์ฆ๊ฐ์ํค๊ณ ๊ฐ์์ํค๋ ์ํฉ
- ์ด์์ ์ผ๋ก๋ counter๊ฐ 5๊ฐ ๋ ๊ฒ์ผ๋ก ์์์ด ๊ฐ๋ค. ํ์ง๋ง ๊ทธ๋ ์ง ์๋ค.
Producer | Consumer |
register_1 = counter (register_1 = 5) | |
register_1 = register_1 + 1 (register_1 = 6) | |
register_2 = counter (register_2 = 5) | |
register_2 = register_2 - 1 (register_2 = 4) | |
counter = register_1 (counter = 6) | |
counter = register_2 (counter = 4) |
synchronization problem ๊ณผ์
- counter์ ๊ฐ์ด 5์ด๊ธฐ ๋๋ฌธ์ producer์ consumer๋ชจ๋ counter์ ๊ฐ์ 5๋ก ๋ฐ์์จ๋ค. ๊ทธ๋์ register_1, register_2์๋ ๊ฐ๊ฐ 5๊ฐ ์ ์ฅ์ด ๋๋ค.
- producer์ consumer๋ ๊ฐ๊ฐ register์ ๊ฐ์ 1 ์ฆ๊ฐ์ํค๊ณ ๊ฐ์์ํจ๋ค.
- register์ ๊ฐ์ counter์ ์ ์ฅํ๋ ๊ณผ์ ์์ producer์ 6์ ๊ฐ์ ๋ฐ๊ณ , consumer์์๋ 4์ ๊ฐ์ ๋ฐ์์ ํ์ธํ ์ ์๊ณ ์ด๋ problem์ด ๋ฐ์ํ๋ค.
๋ฐ๋ผ์,
์ด์ฒ๋ผ ํ๋ก์ธ์ค๊ฐ ์ด๋ค ์์๋ก ๋ฐ์ดํฐ์ ์ ๊ทผํ๋๋์ ๋ฐ๋ผ ๊ฒฐ๊ณผ ๊ฐ์ด ๋ฌ๋ผ์ง ์ ์๋ ์ํฉ์ Race condition(๊ฒฝ์ ์ํ)๋ผ๊ณ ํ๋ค.
race condition์ ํด๊ฒฐํ๊ธฐ ์ํด์ synchronization์ด ๋์ด์ ธ์ผ ํ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
2. The Critical-Section Problem
ํ๋ก์ธ์ค ๋๊ธฐํ์ ๋ํ ๋ฌธ์ ๋ critical section problem์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ ๋ฌธ์ ๋ก๋ถํฐ ์์ํ๋ค.
์ฌ๊ธฐ์ n๊ฐ์ ํ๋ก์ธ์ค {p0, p1, ..., p(n-2)}๊ฐ ์กด์ฌํ๋ค๊ณ ํ์.
๊ทธ ์ ์ critical section์ด๋?
- ์ฝ๋์์ race condition์ด ๋ฐ์ํ ์ ์๋ ํน์ ๋ถ๋ถ์ critical section์ด๋ผ๊ณ ํ๋ค.
- critical section์ด ์ฌ์ฉ๋๋ ์์คํ ์์๋ ํ ํ๋ก์ธ์ค๊ฐ ์์ ์ ์๊ณ๊ตฌ์ญ์์ ์ํํ๋ ๋์์ ๋ค๋ฅธ ํ๋ก์ธ์๋ค์ ๊ทธ๋ค์ ์๊ณ๊ตฌ์ญ์ ๋ค์ด๊ฐ ์ ์๋ค.
์ฆ, critical-section problem์ด๋ ํ๋ก์ธ์๋ค์ด ๋ฐ์ดํฐ๋ฅผ ํ๋ ฅ์ ์ผ๋ก ๊ณต์ ํ๊ธฐ ์ํ์ฌ ์์ ๋ค์ ํ๋์ ๋๊ธฐํํ ๋ ์ฌ์ฉํ ์ ์๋ ํ๋ก์ฝํจ(์ฝ์)์ ์ค๊ณํ๋ ๊ฒ์ด๋ค.
๊ฐ ํ๋ก์ธ์ค๋ ์์ ์ critical section์ผ๋ก ์ง์ ํ๋ ค๋ฉด entry section์์ ์ง์ ํ๊ฐ๋ฅผ ์์ฒญํด์ผ ํ๊ณ , critical section ๋ค์๋ exit section์ด ๋ฐ๋ผ์ฌ ์ ์๋ค. ์ฝ๋์ ๋๋จธ์ง ๋ถ๋ถ๋ค์ ์ด์นญํ์ฌ remainder section์ด๋ผ๊ณ ํ๋ค.
์ด๋ฅผ ์ฝ๋๋ก ๋ํ๋ด๋ฉด ์๋์ ๊ฐ๋ค.
do{ entry section critical section exit section remainder section }while(true);

๊ฐ ํ๋ก์ธ์์์ critical section์ ๋ฐ์ดํฐ๋ shared data์์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์๋ค.
Critical Section Problem์ ํด๊ฒฐํ๊ธฐ ์ํด์ ๋ช๊ฐ์ง ์กฐ๊ฑด์ ์ถฉ์กฑํด์ผ ํ๋ค.
- Mutual Excludion(์ํธ ๋ฐฐ์ฌ) : ์ด๋ฏธ ํ process๊ฐ critical section์์ ์์ ์ค์ด๋ฉด ๋ค๋ฅธ process๋ critical section์ ์ง์ ํด์๋ ์๋๋ค.
- Progress(์งํ) : critical section์์ ์์ ์ค์ธ process๊ฐ ์๋ค๋ฉด ๋ค๋ฅธ process๊ฐ critical section์ ์ง์ ํ ์ ์์ด์ผ ํ๋ค.
- Bounded Waiting(ํ์ ๋๊ธฐ) : critical section์ ์ง์ ํ๋ ค๋ process๊ฐ ๋ฌดํํ๊ฒ ๋๊ธฐํด์๋ ์๋๋ค.
Critical-section Handling in OS
- pid๋ฅผ ํ ๋นํ ๋ race condition์ ์
- ํ๋ก์ธ์ค p0์ p1์ด ๋์์ fork()๋ฅผ ์ด์ฉํ์ฌ child processes๋ฅผ ๋ง๋ค๋ ค๊ณ ํ๋ค.
- ๋ค์์ผ๋ก ์ด์ฉ๊ฐ๋ฅํ process์ id(pid)๋ฅผ ๋ํ๋ด๋ 'next_available_pid' ๋ณ์์์ race condition์ด ์ผ์ด๋๋ค.
- ๋ง์ผ mutual exclusion(์ํธ ๋ฐฐ์ฌ)๊ฐ ์๋ค๋ฉด ๊ฐ์ pid๊ฐ ๋๊ฐ์ ๋ค๋ฅธ ํ๋ก์ธ์ค์ ๋ฐฐ์ ๋ ์ ์๋ค.

- ์ด์์ฒด์ ๋ด์์ critical section์ ๋ค๋ฃจ๊ธฐ ์ํด Preemptive kernels๊ณผ Non-preemptive kernels์ ๋๊ฐ์ง ์ผ๋ฐ์ ์ธ ์ ๊ทผ๋ฒ์ด ์ฌ์ฉ๋๋ค.
- preemptive kernels(์ฐ์ ์์ ๋์๊ฑฐ)
- ํ๋ก์ธ์ค๊ฐ ์ปค๋ ๋ชจ๋์์ ์ํ๋๋ ๋์ ์ ์ ๋๋ ๊ฒ์ ํ์ฉํ๋ค.
- ์ ์ ํ ์ปค๋์ ๋ํด์๋ ๋์ผํ ์ฃผ์ฅ์ ํ ์ ์์ด race condition์ด ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ณต์ ๋๋ ์ปค๋ ์๋ฃ๊ตฌ์กฐ์์ race condition์ด ๋ฐ์ํ์ง ์๋๋ค๋ ๊ฒ์ ๋ณด์ฅํ๋๋ก ์ ์คํ๊ฒ ์ค๊ณ๋์ด์ผ ํ๋ค.
- Non-preemptive kernels
- ์ปค๋ ๋ชจ๋์์ ์ํ๋๋ ํ๋ก์ธ์ค์ ์ ์ ์ ํ์ฉํ์ง ์๊ณ ์ปค๋ ๋ชจ๋ ํ๋ก์ธ์ค๋ ์ปค๋์ ๋น ์ ธ๋๊ฐ ๋๊น์ง ๋๋ ๋ด์๋ ๋๊น์ง ๋๋ ์๋ฐ์ ์ผ๋ก CPU์ ์ ์ด๋ฅผ ์๋ณดํ ๋๊น์ง ๊ณ์ ์ํ๋๋ค.
- ํ ์๊ฐ์ ์ปค๋ ์์์ ์คํ ์ค์ธ ํ๋ก์ธ์ค๋ ํ๋๋ฐ์ ์์ผ๋ฏ๋ก race condition์ ์ผ๋ คํ ํ์๋ ์๋ค.
์ปค๋๋ชจ๋ ํ๋ก์ธ์๊ฐ ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์๋ฅผ ์๋ํ๊ธฐ ์ ์ ์ค๋ซ๋์ ์คํํ ์ํ์ด ์ ๊ธฐ ๋๋ฌธ์ ์ ์ ํ ์ปค๋์ ๋ ์๋ต์ด ๋ฏผ์ฒฉํ ์ ์๋ค. ํ์ง๋ง ์ ์ ํ ์ปค๋์ ์ค๊ณํ๊ธฐ ์์ ๊ฒฝ์ ์กฐ๊ฑด์ ์ ๊ณ ๋ คํด์ผ๋ง ํ๋ค.
3. Peterson's Solution
Peterson's Solution์ด๋ critical-section problem์ ๋ค๋ฃจ๊ธฐ ์ํ ๊ณ ์ ์ ์ธ ์ํํธ์จ์ด ๊ธฐ๋ฐ ํด๊ฒฐ์ฑ ์ด๋ค.
- modern architecture์๋ ์ฌ์ฉ๋ ์ ์๋์ง๋ ๋ณด์ฅ๋์ง ์์
- ํ์ง๋ง ๊ทธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ์๋ ์ข์ ์๊ณ ๋ฆฌ์ฆ ์ค๋ช ์ด๋ค.
- Critical section๊ณผ Remainder section์ ๋ฒ๊ฐ์ ๊ฐ๋ฉฐ ์คํํ๋ ๋๊ฐ์ ํ๋ก์ธ์(pi, pj)๋ก ํ์ ๋๋ค.
- load์ store machine language ๋ช ๋ น์ด๊ฐ atomicํ๋ค. ์ฆ ๋ ๋ช ๋ น์ด๋ ์คํ์ค์ ์ค๋จํ์ง ์๋๋ค(interrupt ๋์ง ์๋๋ค.)
- ๋ ํ๋ก์ธ์ค๊ฐ ๋ ๊ฐ์ ๋ฐ์ดํฐ ํญ๋ชฉ์ ๊ณต์ ํ๋๋ก ํ์ฌ ํด๊ฒฐํ๋ค.
- int turn; //critical section์ผ๋ก ์ง์ ํ ์๋ฒ์ ๋ํ๋ด๋ ๋ณ์
- boolean falg[2]; // ๊ฐ ํ๋ก์ธ์๊ฐ critical section์ผ๋ก ์ง์ ํ ์ค๋น๊ฐ ๋์๋ค๋ ๊ฒ์ ํํํ ๋ฐฐ์ด
Pi์ Peterson ์๊ณ ๋ฆฌ์ฆ
int turn; boolean flag[2]; //flag[i] == true -> pi ์ค๋น๋๋ค! ... while(true){ flag[i] = true; turn = j; while(falg[j] && turn == j); /* critical section */ flag[i] = false; /* remainder section */ }
peterson's solution์ ๊ณผ์ (์ํ)
p0, p1์ ํ๋ก์ธ์๋ค์ด ์กด์ฌํ๋ค๊ณ ๊ฐ์ ํ์.
- p0๊ฐ ๋จผ์ ์์
- flag[0] = true
- turn = 1
- ๊ทธ ๋ค๋ก ๋ฐ๋ก p1๋ ์์
- flag[0] = true
- flag[1] = true
- turn = 1 -> 0
- p0 critical section ์ง์
( while(flag[1] && turn == 1); -> false)
- flag[0] = true -> false
- flag[1] = true
- turn = 0
- p1 critical section ์ง์
( while(flag[0] && turn == 0); -> false)
- flag[0] = false
- flag[1] = false
- turn = 0
- p0 ์
์ฅ์์ critical section ๋ค์์ผ๋ก while๋ฌธ์ ๋ ๋๊ณ ์๋ค. ๊ทธ๋ฐ๋ฐ 4๋ฒ์์ flag[1] = false๊ฐ ๋์ผ๋ฏ๋ก p0์ critical section์ง์
๊ฐ๋ฅ
- flag[0] = true-> false(CS ์ง์ ์ดํ)
- flag[1] = false
- turn = 1
- p1์์๋ turn = 0์ผ๋ก ๋ฐ๊พธ๋ฏ๋ก p0์ดํ๋ก critical section ์ง์ ๊ฐ๋ฅ, ๊ณ์ ๋ฐ๋ณต์ -> atomic

Proof of Peterson's Solution
peterson's solution์ด critical section ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ 3๊ฐ์ง ์๊ตฌ์กฐ๊ฑด์ ๋ง์กฑํด์ผ ํ๋ค.
- Mutual Exclusion(์ํธ๋ฐฐ์ฌ)
- ๋ง์ฝ pi์ pj๊ฐ ๋๋ค critical section์ ๋ค์ด๊ฐ๋ค๋ฉด,
- flag[0] = flag[1] = true ์ผ์๋ฐ์ ์๊ณ
- turn๋ 0, 1๋๋ค ํด๋น๋์ด์ ธ์ผ๋ง ํ๋ค. ํ์ง๋ง turn์ ๊ทธ๋ด ์ ์๋ค.
- ๊ทธ๋ฌ๋ฏ๋ก mutual exclusion์ ๋ง์กฑํ๋ค.
- Progress(์งํ) & Bounded waiting(ํ์ ๋๊ธฐ)
- pi์ blocking condition : while(flag[j] && turn == j);
- ๋ง์ฝ pj๊ฐ ์์ง critical section์ ๋ค์ด๊ฐ ์ค๋น๊ฐ ์๋๋ค๋ฉด : flag[j] = false; -> pi๋ critical section์ ๋ค์ด๊ฐ ์ ์์!
- ๋ง์ฝ pj๊ฐ while๋ฌธ์์ ๊ธฐ๋ค๋ฆฌ๊ณ ์๊ณ , turn์ i, j ๋ ๋ค ๊ฐ๋ฅ์ผ๋
- ๋ง์ฝ turn = i๊ฐ ๋๋ค๋ฉด pi๋ critical section์ ๋ค์ด๊ฐ
- ๋ง์ฝ turn = j๊ฐ ๋๋ค๋ฉด pj๋ critical section ์ ๋ค์ด๊ฐ
- pj๊ฐ critical section์ ๋๋ธ๋ค๋ฉด pj๋ flag[j] = false๋ก ๋ง๋ ๋ค. ๊ทธ๋ฆฌ๊ณ pi๋ critical section์ผ๋ก ๋ค์ด๊ฐ ์ ์๋ค. pj๊ฐ turn์ i๋ก ๋ฐ๊ฟจ๊ธฐ ๋๋ฌธ!
- ๊ทธ๋ฌ๋ฏ๋ก pi๋ critical section์ผ๋ก ๋ค์ด๊ฐ ์ ์๊ณ (progress), ๊ทธ์ ํ๋์ process๋ง ๊ธฐ๋ค๋ฆฌ๊ฒ ๋๋ค (bounded waiting)
- pi์ blocking condition : while(flag[j] && turn == j);
Peterson's solution์ ์ต์ ์ปดํจํฐ๊ตฌ์กฐ์์๋ ์๋ํ๋ค๊ณ ๋ณด์ฅ๋์ง ์๋๋ค. ์ฃผ๋ ์ด์ ๋ ์์คํ ์ฑ๋ฅ์ ํฅ์ํ๊ธฐ ์ํด ํ๋ก์ธ์ค ๋๋ ์ปดํ์ผ๋ฌ๊ฐ ์ข ์์ฑ์ด ์๋ ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ ์์ ์ ์ฌ์ ๋ ฌ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ก ๋ค์ด, Peterson ํด๊ฒฐ์์ entry section์ ์ฒซ ๋ ๋ฌธ์ฅ์ ์์๋ฅผ ๋ฐ๊พธ๊ฒ ๋๋ฉด(์๋ ์์) critical solution์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ํ ์ ์๋ค.
entry section์์์ ์ฒซ ๋๋ฌธ์ฅ์ ์์๋ฅผ ๋ฐ๊ฟจ์ ๋ ์์
- ๋ ๊ฐ์ thread๊ฐ ๊ณต์ ํ๋ ๋ฐ์ดํฐ
- boolean flag = false;
- int x = 0;
- Thread1
- while(!flag);
- print x;
- Thread2
- x = 100;
- flag = true;
- ์์๋๋ output
- 100์ด ์ถ๋ ฅ ๋ ๊ฒ์.
- ํ์ง๋ง ๋ง์ฝ Thread2์์ ๋ ์ค์ ์์น๋ฅผ ์๋ก ๋ฐ๊พผ๋ค๋ฉด? -> output = 0
์ด ์์๊ฐ peterson's solution์ผ๋ก ์ ์ฉ๋๋ค๋ฉด?
4. Hardware Support for Synchronization
Critical Section Problem์ ์ํํธ์จ์ด ๊ธฐ๋ฐ ํด๊ฒฐ์ฑ (peterson's solution)์ ์ต์ ์ปดํจํฐ๊ตฌ์กฐ์์ ์๋ํ์ง ์์ ์ ์๋ค.
๊ทธ๋์ hardware์ ์ง์์ด ํ์ํ๋ฐ, 4์ ์์๋ Critical section problem์ ํด๊ฒฐํ๊ธฐ ์ํ ์์์ ์ ๊ณตํ๋ ์ธ ๊ฐ์ง ํ๋์จ์ด ๋ช ๋ น(hardware support)์ ์ ์ํ๋ค.
- Memory barriers
- Hardware instructions
- Atomic variables
1) Memory Barriers(๋ฉ๋ชจ๋ฆฌ ์ฅ๋ฒฝ)
: ์ปดํจํฐ๊ตฌ์กฐ๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ ๋ค๋ฅธ ๋ชจ๋ ํ๋ก์ธ์๋ก ์ ํํ๋ ๋ช ๋ น์ด๋ฅผ ์ ๊ณตํ์ฌ ๋ค๋ฅธ ํ๋ก์ธ์์์ ์คํ ์ค์ธ ์ค๋ ๋์ ๋ฉ๋ชจ๋ฆฌ ๋ณ๊ฒฝ ์ฌํญ์ด ๋ณด์ด๋ ๊ฒ์ ๋ณด์ฅํ๋ค. ์ด๋ฌํ ๋ช ๋ น์ด๋ฅผ ๋ฉ๋ชจ๋ฆฌ ์ฅ๋ฒฝ(Memory Barriers) ๋๋ ๋ฉ๋ชจ๋ฆฌ ํ์ค(Memory Fences)๋ผ๊ณ ํ๋ค.
- ๋ฉ๋ชจ๋ฆฌ ์ฅ๋ฒฝ ๋ช ๋ น์ด๊ฐ ์คํ๋ ๋, ์์คํ ์ ํ์ load ๋๋ store ์ฐ์ฐ์ด ์ํ๋๊ธฐ ์ ์ ๋ชจ๋ load ๋ฐ store ์ฐ์ฐ์ด ๋ฉ๋ชจ๋ฆฌ์์ ์๋ฃ๋๋๋ก ํ๋ค. ๋ฐ๋ผ์ ๋ช ๋ น์ด ์ฌ์ ๋ ฌ ๋๋๋ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฅ๋ฒฝ์ future load ๋๋ store ์์ ์ด ์ํ๋๊ธฐ ์ ์ ์ ์ฅ ์์ ์ด ๋ฉ๋ชจ๋ฆฌ์์ ์๋ฃ๋์ด ๋ค๋ฅธ ํ๋ก์ธ์์ ๋ณด์ด๋๋ก ํ๋ค.
- ์ด ์์ ์ ๋งค์ฐ low-level(๋ฎ์ ์์ค)์ ์์ ์ด๋ค.
- ์ผ๋ฐ์ ์ผ๋ก Mutual Exclusion์ ๋ณด์ฅํ๋ ํน์ ์ฝ๋๋ฅผ ์์ฑํ ๋ ์ปค๋ ๊ฐ๋ฐ์๋ง ์ฌ์ฉํ๋ค.
์์)
์์ ๋์๋ x = 100์ ์ถ๋ ฅํ๋ ์์๋ฅผ ๊ฐ์ ธ์๋ณด์
//Thread1 //x ์ ์ flag๊ฐ load ๋๋ ๊ฒ์ ๋ณด์ฅํจ while(!flag) memory_barrier(); print x;
//Thread2 //x ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ensure. flag๊ฐ assign ๋๊ธฐ ์ ์ x = 100; memory_barrier(); flag = true;
memory_barrier();์ ํด์ค์ผ๋ก์จ x์ flag๊ฐ ์ ์ฅ๋๋ ๊ฒ์ ๋ณด์ฅํ๋ค.
//Peterson's solution while(true){ flag[i] = true; memory_barrier(); turn = j; while(flag[j] && turn == j); ... }
2) Hardware Instructions
๋ง์ ํ๋ ๊ธฐ๊ณ๋ค์ ํ ์๋(word)์ ๋ด์ฉ์ ๊ฒ์ฌํ๊ณ ๋ณ๊ฒฝํ๊ฑฐ๋, ๋ ์๋์ ๋ด์ฉ์ atomicalํ๊ฒ(๊ณ์์ ์ผ๋ก) ๊ตํํ ์ ์๋, ์ฆ ์ธํฐ๋ฝํธ ๋์ง ์๋ ํ๋์ ๋จ์๋ก์, ํน๋ณํ ํ๋์จ์ด ๋ช ๋ น์ด๋ค์ ์ ๊ณตํ๋ค. ์ฐ๋ฆฌ๋ ์ด๋ค์ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ๋ฐฉ์์ผ๋ก Critical Section ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
- Test-and-Set instruction
- Compare-and-Swap instruction
Test-and-Set instruction
//Definition boolean test_and_set(boolean *target){ boolean rv = *target; *target = true; return rv; }
- ๊ณ์์ ์ผ๋ก(atomically) ์คํ๋๋ค.
- ๋งค๊ฐ๋ณ์์ ๊ธฐ์กด ๊ฐ(original value)์ returnํ๋ค.
- ๋งค๊ฐ๋ณ์์ ๊ฐ์ ์ ๊ฐ์ ์ค์ ํ๋ค.
์ด๋ฅผ ํ์ฉํ Critical Section์ Mutual Exclusion ํด๊ฒฐ ์๊ณ ๋ฆฌ์ฆ์ ์๋์ ๊ฐ๋ค.
do{ while(test_and_set(&lock)); /* critical section */ lock = false; /* remainder section */ }while(true);
๋ง์ฝ process๊ฐ ๋๊ฐ(p0, p1)๊ฐ ์๋ค๊ณ ํ์.
๊ธฐ์กด์ lock์ด false์ด๋ฉด, p0๋ false๋ฅผ ๋ฐํ๋ฐ์ critical section์ผ๋ก ๋ค์ด๊ฐ ์ ์๋ค. ํ์ง๋ง ์ค์ lock์ ๊ฐ์ true๋ก ๋ณ๊ฒฝ๋์์ผ๋ p1์ ๊ณ์ while์ ๊ฐํ์๊ฒ ๋๋ค. p0์์ critical section์ผ๋ก ๋ค์ด๊ฐ๋ค๋ฉด lock์ false๋ก ๋ฐ๋๋ฉด์ p1์ while์กฐ๊ฑด์ธ test_and_set์ ๋ฐํ์ด false๊ฐ ๋์ด p1์ critical section์ผ๋ก ๋ค์ด๊ฐ๋ค. ์ด๋ lock์ ๋ true๋ก ๋ฐ๋๋ฏ๋ก p0์ while๋ฌธ์ ๊ฐํ๊ฒ ๋๋ค. ์ด๋ ๋ฏ p0์ p1์ด ์๋ค๊ฐ๋ค ๊ณ์์ ์ผ๋ก ๋ฐ๋ณตํ ์ ์๋ค.
Compare-and-Swap instruction
//Definition int compare_and_swap(int *value, int expected, int new_value){ int temp = *value; if (*value == expected) *value = new_value; return temp; }
- ๋ํ atomicalํ๊ฒ ์๋๋๋ค.
- ์ ๋ฌ๋ ๋งค๊ฐ๋ณ์ ๊ฐ์ ๊ธฐ์กด ๊ฐ(original value)๋ฅผ return ํ๋ค.
- ๋งค๊ฐ๋ณ์์ ๊ฐ์ new_value๋ก ๋ฐ๊ฟ์ค๋ค. ํ์ง๋ง ์ด๋ *value == expected ๊ฐ true์ผ๋๋ง ์คํํ๋๋ก ํ๋ค.
์ด๋ฅผ ํ์ฉํ Critical Section์ Mutual Exclusion ํด๊ฒฐ ์๊ณ ๋ฆฌ์ฆ์ ์๋์ ๊ฐ๋ค.
while(true){ while(compare_and_swap(&lock, 0, 1) != 0); /* critical section */ lock = 0; /* remainder section */ }
์ญ์๋ ํ๋ก์ธ์ค๊ฐ p0, p1 ๋๊ฐ๊ฐ ์๋ค๊ณ ํ์
์๋ lock = 0์ด๋ผ๊ณ ํ๊ณ ์์ํ์. p0์ด ๋จผ์ compare_and_swap์ ์คํํ๋ฉด ๊ธฐ์กด๊ฐ์ด๋ 0์ ๋ฐํํ๋ฏ๋ก while๋ฌธ ์กฐ๊ฑด์ false๊ฐ ๋์ด critical section์ผ๋ก ๋ค์ด๊ฐ๋ค. p1 ์ ์ฅ์์ ๋ณด๋ฉด lock์ 1๋ก ๋ฐ๊ผ์ผ๋ compare_and_swap์ด 1์ ๋ฐํํ๋ฏ๋ก ์กฐ๊ฑด์ true๊ฐ ๋์ด critical section์ผ๋ก ๋ค์ด๊ฐ์ง ๋ชปํ๋ค. ํ์ง๋ง p0๊ฐ critical section์์ lock=0์ ์ํํ๊ฒ ๋๋ฉด ๊ทธ๋ p1์ compare_and_swap์ด 0์ ๋ฐํํ์ฌ ์กฐ๊ฑด์ด false๊ฐ ๋๊ณ critical section์ผ๋ก ๋ค์ด๊ฐ ์ ์๋ค. ์ด๋ฌํ ์ผ์ด ๋ฐ๋ณต์ ์ผ๋ก ์ํ๋๋ค.
์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ํํํ๋ฉด ์๋์ ๊ฐ๋ค.

ํ์ง๋ง, ์์ ์์๋ bounded waiting ์๊ตฌ๋ฅผ ์ถฉ์กฑํ์ง ๋ชปํ๋ค.
์ด์ ๋ ์๋์ ๊ฐ๋ค.

Bounded waiting mutual exclusion์ ๋ง์กฑํ๊ธฐ ์ํด์ ์๋์ ๊ฐ์ ์ฝ๋๋ก ์์ฑ์ด ๋์ด์ผ ํ๋ค.
boolean waiting[n]; //n = process๊ฐ์, initialized to false int lock; //initialized to 0 while(true){ waiting[i] = true; key = 1; while(waiting[i] && key == 1) key = compare_and_swap(&lock, 0, 1); waiting[i] = false; /* critical section */ j = (i +1) % n; while((j != i) && !waiting[j]) j = (j+1) % n; if(j == i) lock = 0; else waiting[j] = false; /* remainder section */ }
pi๊ฐ critical section์ ์ง์ ํ๋ ๊ฒฝ์ฐ๋ ์ค์ง waiting[i] == false ์ด๋ ์ง key == 0 ์ด ๋์ด์ผ ํ๋ค. lock์ด 0์ผ ๋์๋ง key๊ฐ 0์ด ๋๊ณ lock ์ด 1๋ก ๋ฐ๋๋ฉด์ ๋ฌดํ ๋ฃจํ์์ ๋น ์ ธ๋์ฌ ์ ์๋ค.
waiting[i]๋ฅผ false๋ก ๋ฐ๊พธ๊ณ critical section์ ์คํํ ๋ค, i๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฆ๊ฐ์์ผ ์์ ๊ณผ ๊ฐ์ ๋๊น์ง ํน์ i๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ ๋๊น์ง ๋ฌดํ ๋ฃจํ๋ฅผ ๋๊ณ , ์ ํ๋ ํ๋ก์ธ์ค๋ฅผ critical section์ ์ง์ ํ ์ ์๋๋ก ํด์ฃผ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
3) Atomic Variables
Atomic Variable์ integers ๋ฐ booleans๊ณผ ๊ฐ์ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ์ ํ์ ๋ํ Atomic ์ฐ์ฐ์ ์ ๊ณตํ๋ค. Atomic Variable์ ์นด์ดํฐ๊ฐ ์ฆ๊ฐํ ๋์ ๊ฐ์ด ๊ฐฑ์ ๋๋ ๋์ ๋จ์ผ ๋ณ์์ ๋ํ ๋ฐ์ดํฐ ๊ฒฝ์์ด ์์ ์ ์๋ ์ํฉ์์ ์ํธ ๋ฐฐ์ ๋ฅผ ๋ณด์ฅํ๋๋ฐ ์ฌ์ฉ๋ ์ ์๋ค.
์)
//increment function void increment(atomic_int *v){ int temp; do{ temp = *v; }while(temp != compare_and_swap(v, temp, temp+1)); } //p1 : temp = 10, *v = 11 //p2 : temp = 10, *v = 12
5. Mutex Locks
Mutex lock์ mutual exclusion lock์ ์ถ์ฝํํ๋ก Critical section ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ Hardware๊ธฐ๋ฐ์ ํด๊ฒฐ์ฑ (ex.Peterson's solution)๋ณด๋ค ์์ ์์ค์ ํด๊ฒฐ์ฑ ์ด๋ค. Critical Section์ ๋ณดํธํ๊ณ , ๋ฐ๋ผ์ Race condition์ ๋ฐฉ์งํ๊ธฐ ์ํด์ mutex lock์ ์ฌ์ฉํ๋ค.
Mutex lock์์๋ ์ธ๊ฐ์ง๋ฅผ ์์์ผ ํ๋ค.
- acquire(): lock์ ํ๋ํ๋ ํจ์
- release(): lock์ ๋ฐํํ๋ ํจ์
- available: lock์ ๊ฐ์ฉ ์ฌ๋ถ๋ฅผ ํ์ํ๋ ๋ณ์
acquireํจ์์ releaseํจ์๋ ๋ฐ๋์ atomicํ๊ฒ ์๋๋์ด์ผ ํ๋ค.
//acquire ํจ์ acquire(){ /* busy waiting */ while(!available); available = false; }
//release ํจ์ release(){ available = true; }
mutex lock์ ์ฌ์ฉํ์ฌ critical section problem์ ํด๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์๋์ ๊ฐ๋ค.
while(true){ acquire lock critical section release lock remainder section }
ํ์ง๋ง ์ด๋ฌํ ๊ตฌํ ๋ฐฉ์์ ๋จ์ ์ busy waiting์ ํด์ผํ๋ค๋ ๊ฒ์ด๋ค. busy waiting์ด๋ ํ๋ก์ธ์ค๊ฐ critical section์ ์๋ ๋์ critical section์ ๋ค์ด๊ฐ๊ธฐ ์ํ๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๋ค์ acquire()ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐ๋ณต๋ฌธ์ ๊ณ์ ์คํํด์ผ ํ๋ ์ํฉ์ ๋งํ๋ค. ์ด๋ฌํ busy waiting์ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ ์์ฐ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ CPU ์ฃผ๊ธฐ๋ฅผ ๋ญ๋นํ๋ค.
์ด๋ฌํ busy waiting์ ์ผ์ผํฌ ์ ์๋ mutex lock๊ณผ ๊ฐ์ ์ ํ์ spinlock(์คํ๋ฝ)์ด๋ผ๊ณ ๋ถ๋ฆฌ๊ธฐ๋ ํ๋ค.
6. Semaphores
Semaphores ์ญ์ ๋๊ธฐํ ํด์ด๋ค. ๊ทธ๋ฐ๋ฐ Semaphores์ Mutex lock๋ณด๋ค ๋ ์ธ๋ จ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ธ๋งํฌ๋ ์นด์ดํฐ๋ฅผ ์ด์ฉํด ๋์์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋ ํ๋ก์ธ์ค๋ฅผ ์ ํํ๋ค. ์ธ๋งํฌ๋ P์ V๋ผ๋ ๋ช ๋ น์ผ๋ก ์ ๊ทผํ ์ ์๋ค.
์๋ ์ฝ๋์์ Semaphore S ๋ ์ ์ ๋ณ์๋ก์, ์ด๊ธฐํ๋ฅผ ์ ์ธํ๊ณ ๋ ๋จ์ง ๋๊ฐ์ ํ์ค atomical ์ฐ์ฐ wait()์ signal()๋ก๋ง ์ ๊ทผํ ์ ์๋ค.
wait()๋ ์๋์ ๊ฐ๋ค.
wait(S){ while(S <= 0); //waits for the lock S--; // holds the lock }
signal()๋ ์๋์ ๊ฐ๋ค.
signal(S){ S++; // release the lock }
1) Semaphores Usage
์ด์์ฒด์ ๋ Counting๊ณผ binary ์ธ๋งํฌ๋ฅผ ๊ตฌ๋ถํ๋ค.
- Counting Semaphores
- Interger value S๋ ์ ํ์๋ ๊ฐ์ ๊ฐ์ง
- ์ ํํ ๊ฐ์๋ฅผ ๊ฐ์ง ์์(๊ฐ๋ฅํ ์์์ ๊ฐ์๋ก ์ด๊ธฐํ ๋จ)์ ๋ํ ์ ๊ทผ์ ์ ์ดํ๋๋ฐ ์ฌ์ฉ๋ ์ ์๋ค.
- Binary Semaphores
- Integer value๋ 0๊ณผ 1 ์ค์๋ง ๊ฐ๋ฅํ๋ค.
- mutex lock๊ณผ ๋น์ทํ๋ค.
2) Semaphore Implememtation
์ wait()์ while์ spinlock์ผ๋ก busy waiting์ด ์ผ์ด๋๋ค. ์ด๋ฌํ busy waiting์ ํผํ๊ธฐ ์ํด ์ธ๋งํฌ S๋ฅผ ๋๊ธฐํ๋ฉด์ ์ผ์ ์ค์ง๋ ํ๋ก์ธ์ค๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ signal()์ฐ์ฐ์ ์คํํ๋ฉด ์ฌ์์๋์ด์ผ ํ๋ค. ํ๋ก์ธ์ค๋ sleep()์ ์ํด์ ์ผ์ ์ค์ง๋๊ณ wakeup()์ ์ํด ์ฌ์์๋๋ค.
์ธ๋งํฌ๋ฅผ ์ด์ฉํด์ critical section problem์ ํด๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ๊ธฐ ์ํ ์ธ๋งํฌ์ ์ ์๋ ์๋์ ๊ฐ๋ค.
typedef struct{ int value; struct process *list; // head of linked list for waiting queue }semaphore;
๋ณ๊ฒฝ๋ wait()์ signal()์ ์๋์ ๊ฐ๋ค.
wait(semaphore *S){ S->value--; if(S->value < 0){ add this process to S->list; sleep(); //suspend } }
signal(semaphore *S){ S->value++; if(S->value <= 0){ remove a process P from S->list; wakeup(P); //resume } }
wakeup()๊ณผ sleep()๋ ํ๋ก์ธ์ค๋ฅผ ์ผ์ ์ค์ง ๋๋ ์ฌ์คํ์ํค๋ ์ด์์ฒด์ ์ ๊ธฐ๋ณธ์ ์ธ ์์คํ ์ฝ์ด๋ค.
์ธ๋งํฌ์ ํ๋ก์ธ์ค ๋ฆฌ์คํธ๋ Bounded Waiting์ ๋ณด์ฅํ๋๋ก ์ ๊ตฌํํด์ผ๋ง ํ๋ค.
๋จ์ผ Processor ํ๊ฒฝ์์๋ wait()์ signal()์ด atomicํ๊ฒ ์คํ๋๋ ๊ฒ์ ๋ณด์ฅํ๊ธฐ ์ํด ์คํ๋๋ ๋์ ์ธํฐ๋ฝํธ๋ฅผ ๊ธ์งํจ์ผ๋ก์จ ํด๊ฒฐํ ์ ์์ง๋ง, ๋ค์ค ์ฝ์ด ํ๊ฒฝ์์๋ ๋ชจ๋ ์ฒ๋ฆฌ ์ฝ์ด์์ ์ธํฐ๋ฝํธ๋ฅผ ๊ธ์งํ์ฌ์ผ๋ง ํ๋ค. ์ด๋ ๋งค์ฐ ์ด๋ ค์ธ ์ ์์ผ๋ฉฐ ์ฑ๋ฅ์ ์ฌ๊ฐํ๊ฒ ๊ฐ์์ํฌ ์ ์์์ผ๋ก ๋ง์ ๋ถ๋ถ์ ๊ณ ๋ คํด์ผ๋ง ํ๋ค.
7. Monitors(๋ชจ๋ํฐ)
mutex lock ๋๋ Semaphore๋ฅผ ์ฌ์ฉํ ๋์๋ ํ์ด๋ฐ ์ค๋ฅ๋ ๋ฐ์ํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, wait()์ signal()์ ์์๊ฐ ๋ค๋ฐ๋๋ ๊ฒฝ์ฐ, Critical Section์ด ๋๋๊ณ signal()๋์ wait()๊ฐ ํธ์ถ๋๋ ๊ฒฝ์ฐ์ ๊ทธ๋ ๋ค.
Semaphore์ ์ฌ๋ฐ๋ฅธ ์ฌ์ฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
wait(mutex); /* critical section */ signal(mutex);
์ด๋ฌํ ์ค๋ฅ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ํ๊ฐ์ง ์ ๋ต์ ๋ชจ๋ํฐ(Monitor)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
1) Monitors๋?
ํธ๋ฆฌํ๊ณ ํจ๊ณผ์ ์ธ ๋๊ธฐํ ๋๊ตฌ๋ฅผ ์ง์งํ๊ธฐ ์ํ high-level language contructs.
- Monitor type: ๋ชจ๋ํฐ ๋ด๋ถ์์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ์ํ mutual exclusion์ด ๋ณด์ฅ๋๋ ์ผ๋ จ์ ์ฐ์ฐ์ ์งํฉ์ ํฌํจํ๋ ADT์ด๋ค.
- ADT(์ถ์ํ๋ ๋ฐ์ดํฐ ํ, abstract data type)์ ๋ฐ์ดํฐ์ ์ด ๋ฐ์ดํฐ๋ฅผ ์กฐ์ํ๋ ํจ์๋ค์ ์งํฉ์ ํ๋์ ๋จ์๋ก ๋ฌถ์ด ๋ณดํธํ๋ค. ์ด๋ ํจ์์ ๊ตฌํ์ ADT์ ํน์ ํ ๊ตฌํ๊ณผ ๋ ๋ฆฝ์ ์ด๋ค.
- ์ค์ง ํ๋์ ํ๋ก์ธ์ค๋ง ๋ชจ๋ํฐ์์ activeํ๋ค(mutual exclusion)
- Pseudocode syntax of monitor
monitor monitor-name { //shared variable declarations function P1 (...) {...} function P2 (...) {...} function P3 (...) {...} initialization code (...) {...} }
2) Schematic view of a Monitor
monitor์ ๊ฐ๋ต๋๋ ์๋์ ๊ฐ๋ค.

๋ชจ๋ํฐ ์์๋ 3๊ฐ์ง์ components๋ค์ด ์ ์๊ฐ ๋์ด์ผ ํ๋๋ฐ, shared data, operations, initialization code๊ฐ ์ด์ ํด๋น๋๋ค.
๋ํ entry queue๊ฐ ์กด์ฌํ๋๋ฐ, entry queue์์๋ ํ๋ก์ธ์ค๊ฐ ์๋ค. ์ด ํ๋ก์ธ์ค๋ค์ ๋ชจ๋ํฐ์ ๋ค์ด๊ฐ๊ธฐ ์ํด ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ค.
๋ชจ๋ํฐ ๊ตฌ์กฐ๋ฌผ์ ๋ชจ๋ํฐ ์์ ํญ์ ํ๋์ ํ๋ก์ธ์ค๋ง์ด ํ์ฑํ๋๋๋ก ๋ณด์ฅํด ์ค๋ค(mutual exclusion). ํ์ง๋ง ์ง๊ธ๊น์ง ์ ์ํ ๋ชจ๋ํฐ ๊ตฌ์กฐ๋ฌผ์ ์ด๋ค ๋๊ธฐํ ๊ธฐ๋ฒ์ ๋ชจ๋ธ๋งํ๋ ๋ฐ์๋ ์ถฉ๋ถํ ๋ฅ๋ ฅ์ ์ ๊ณตํ์ง ์๋๋ค.
monitor์ ์
- Monitor in Java : Synchronized method
class Producer{ private int product; ... private synchronized void produce(); //mutually exclusive }
synchronized method๋ฅผ ์ด์ฉํ์ฌ mutual exclusion์ ๋ณด์ฅํ ์ ์๋ค.
๋ง์ฝ ์ ์ฝ๋์์ private synchronized void B();๋ผ๋ ํจ์๊ฐ ์ถ๊ฐ๊ฐ ๋๋ค๊ณ ๊ฐ์ ํ์. Process A, Process B๊ฐ ์๋ ์ํฉ์์ PA๊ฐ produce()ํจ์์ ์ ๊ทผํ๊ธธ ์ํ๊ณ PB๊ฐ B()ํจ์์ ์ ๊ทผํ๊ธฐ ์ํ๋ค๊ณ ํ๋ค๋ฉด Synchronized method์ ์ํด์ ์ค์ง ํ ํ๋ก์ธ์ค๊ฐ ํ๋์ ํจ์๋ง ์ ๊ทผํ ์ ์๋ค.
3) Condition Variables
Condition Variables์ ์ถ๊ฐ์ ์ธ ๋๊ธฐํ ๊ธฐ๋ฒ(additional synchronization mechanism)์ด๋ค.
- Condition ํ์ ๋ณ์ ์ ์(Variable declaration)
- condition x, y;
- conditionํ ๋ณ์์ ํธ์ถ๋ ์ ์๋ ์ฐ์ฐ์ ์ค์ง wait()์ signal()์ด๋ค.
- x.wait(); // ์ด ์ฐ์ฐ์ ํธ์ถํ ํ๋ก์ธ์ค๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ x.signal()์ ํธ์ถํ ๋๊น์ง ์ผ์ ์ค์ง ๋์ด์ผ ํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
- x.signal(); // ์ผ์ ์ค์ง๋ ํ๋ก์ธ์ค๋ฅผ ํ์ด์ค๋ค. ๋ง์ฝ waitingํ๊ณ ์๋ ํ๋ก์ธ์ค๊ฐ ์๋ค๋ฉด ์๋ฌด์ผ๋ ์ผ์ด๋์ง ์๋๋ค.

4) Condition Variables Choices
- ๋ง์ฝ process P๊ฐ x.signal()์ ํธ์ถํ๊ณ , process Q๊ฐ x.wait()์์ ์ผ์ ์ค๋จ ๋๋ค๋ฉด, ๋ฌด์์ด ๋ค์์ ์ผ์ด๋ ๊น?
- Q์ P ๋ชจ๋ ๋์์ ์คํ๋ ์ ์๊ธฐ ๋๋ฌธ์ Q๊ฐ ์งํ๋๋ค๋ฉด P๋ ๋๊ธฐํด์ผ ํ๋ค. ๋ชจ๋ํฐ์์๋ ์ค์ง ํ๋์ ํ๋ก์ธ์ค๋ง ์คํ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ์ฌ๊ธฐ์๋ ๋๊ฐ์ง ์ํฉ์ด ์ผ์ด๋ ์ ์๋ค. ๊ทธ๊ฒ์ ์๋์ ๊ฐ๋ค.
- ๋ ๊ฐ์ง ์ต์
(์ํฉ)
- Signal and wait: ๋ง์ฝ P๊ฐ x.signal()์ ๋ถ๋ ๋ค๋ฉด Q๊ฐ ์คํ๋๊ณ P๋ Q๊ฐ monitor์ ๋ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ ๋ค๋ฅธ condition์ ๊ธฐ๋ค๋ด์ผ ํ๋ค. (Q๊ฐ ๋จผ์ ์์)
- Signal and continue: P๊ฐ x.signal()์ ๋ถ๋ ๋ค๋ฉด Q๋ P๊ฐ monitor์ ๋ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ ๋ค๋ฅธ condition์ ๊ธฐ๋ค๋ ค์ผ ํ๋ค. (P๊ฐ ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ธฐ)
- ์์ ๋์ ๋ชจ๋ ์ฅ๋จ์ ์ด ์กด์ฌํ๋ค. ํ์ง๋ง signal and continue๊ฐ ์กฐ๊ธ ๋ reasonableํ๋ค.
5) Implementing a Monitor Using Semaphores
๊ฐ ๋ชจ๋ํฐ๋ง๋ค mutex๋ผ๋ binary semaphore๊ฐ ์ ์๋๊ณ ๊ทธ ์ด๊ธฐ ๊ฐ์ 1์ด๋ค. ํ๋ก์ธ์ค๋ ๋ชจ๋ํฐ๋ก ๋ค์ด๊ฐ๊ธฐ ์ ์ wait(mutex)๋ฅผ ์คํํ๊ณ ๋ชจ๋ํฐ๋ฅผ ๋์จ ํ์ signal(mutex)์ ์คํํด์ผ ํ๋ค.
- Funtions to implement(์คํ์ํฌ ํจ์๋ค)
- External procedures
- wait() of condition variable
- signal() of condition variable
๋ชจ๋ํฐ ๊ตฌํ ์ signal-and-wait๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ค. signaling ํ๋ก์ธ์ค๋ ์คํ ์ฌ๊ฐ๋๋ ํ๋ก์ธ์ค๊ฐ ๋ชจ๋ํฐ๋ฅผ ๋ ๋๋์ง ์๋๋ฉด wait()ํ ๋๊น์ง ๊ทธ ์์ ์ด ๋ค์ ๊ธฐ๋ค๋ ค์ผ ํ๋ฏ๋ก next๋ผ๋ binary semaphore ๊ฐ ์ถ๊ฐ๋ก ํ์ํ๊ฒ ๋๊ณ 0์ผ๋ก ์ด๊ธฐํ ๋๋ค.
- ๋๊ฐ์ semaphores๊ฐ ํ์ํ๋ค.
- semaphore mutex = 1; // mutual exclusion
- semaphore next = 0; // signaling process should wait until the resumed process leaves monitor
- int next_count = 0; // the number of precesses suspended on next(semaphore)
- External procedure F
wait(mutex); ... body of F; ... if(next_count > 0) signal(next) else signal(mutex);
- Conditional variables
- Required data
- semaphore x_sem; // (initially, 0)
- int x_count = 0; // wait ํ๊ณ ์๋ ํ๋ก์ธ์ค์ ์
- Required data
x.wait(){ x_count++; if(next_count > 0) signal(next); else signal(mutex); wait(x_sem); x_count--; }
x.signal(){ if(x_count > 0){ next_count++; signal(x_sem); wait(next); next_count--; } }
6) Resuming Precesses within a Monitor
- If several processes queued on conditio variable x, and x.signal() is executed, which process should be resumed?(์กฐ๊ฑด ๋ณ์ x์ ์ฌ๋ฌ ํ๋ก์ธ์ค๊ฐ ์ผ์ ์ค์ง ๋์ด ์์ ๋, ์ด๋ ํ ํ๋ก์ธ์ค๋ฅผ ์ํ ์ฌ๊ฐ์ํฌ ๊ฒ์ธ๊ฐ?)
- FCFS(First Come First Served)์์ด ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉ๋ ์ ์๋ค๊ณ ์๊ฐ์ด ๋ค์ง๋ง ๋ง์ ๊ฒฝ์ฐ ์ด๋ฌํ ๊ฐ๋จํ ์ค์ผ์ค๋ง ๊ธฐ๋ฒ์ ์ถฉ๋ถํ์ง ์๋ค.
- ์ด๋ฅผ ์ํด conditional-wait ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
- ์ด ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ ํํ๋ฅผ ๊ฐ์ง๋ค.
- x.wait(c);
- ์ฌ๊ธฐ์ c๋ ์ ์์ด๋ฉฐ, ์ฐ์ ์์ ๋ฒํธ(priority number)๋ผ๊ณ ๋ถ๋ฆฐ๋ค. ์ผ์ ์ค์ง ๋๋ ํ๋ก์ธ์ค์ ์ด๋ฆ๊ณผ ํจ๊ป ์ ์ฅ๋๋ค.
- x.signal()์ด ์ํ๋๋ฉด ๊ฐ์ฅ ์์ ์ฐ์ ์์ ๋ฒํธ๋ฅผ ๊ฐ์ง ํ๋ก์ธ์ค๊ฐ ๋ค์๋ฒ์ ์ํ ์ฌ๊ฐ ๋๋ค.
7) Single Resource Allocation
๋ชจ๋ํฐ๋ Resource๋ฅผ ์ฌ์ฉํ ์ต๋ ์๊ฐ์ ์ง์ ํ๋ ์ฐ์ ์์ ๋ฒํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฒฝ์ ํ๋ก์ธ์ค ์ค์์ ํ ๊ฐ์ Resource์ ํ ๋นํด ์ค๋ค. ์ด Resource๋ฅผ ์ก์ธ์ค ํ๋ ค๋ ํ๋ก์ธ์ค๋ ์๋์ ์์๋ฅผ ๋ฐ๋ผ์ผ ํ๋ค.
R.acquire(t); ... access the resource; ... R.release;
์ฌ๊ธฐ์ R์ ResourceAllocator type์ ํ instance์ด๋ค.
8) A Monitor to Allocate Single Resource
์๋๋ ADT์ธ ResourceAllocator ๋ชจ๋ํฐ๋ฅผ ๊ตฌํํ ๊ฒ์ด๋ค.
monitor ResourceAllocator{ boolean busy; condition x; void acquire(int time){ if(busy) x.wait(time); busy = true; } void release(){ busy = FALSE; x.signal(); } initialization code(){ busy = false; } }
8. Liveness(๋ผ์ด๋ธ๋์ค)
๋ผ์ด๋ธ๋์ค๋ ํ๋ก์ธ์ค๊ฐ ์คํ life cycle ๋์ ์งํ(progress)๋๋ ๊ฒ์ ๋ณด์ฅํ๊ธฐ ์ํด ์์คํ ์ด ์ถฉ์กฑํด์ผ ํ๋ ์ผ๋ จ์ ์์ฑ์ ๋งํ๋ค.
๋ผ์ด๋ธ๋์ค ์คํจ์ ์: ํ๋ก์ธ์ค๊ฐ lock์ ์ป๊ธฐ ์ํด ๋ฌด๊ธฐํ ๋๊ธฐํ๋ ๊ฒ
liveness ์คํจ์ ์ด์
- Deadlock
- Priority inversion
- Many other reasons
- Deadlock(๊ต์ฐฉ์ํ)
- ๋๊ธฐ ํ๋ฅผ ๊ฐ์ง Semaphore ๊ตฌํ์์ ๋ ๊ฐ ์ด์์ ํ๋ก์ธ์ค๋ค์ด, ์ค๋ก์ง ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค๋ค ์ค ํ๋์ ์ํด์๋ง ์ผ๊ธฐ๋ ์ ์๋ signal()์ ๋ฌดํ์ ๊ธฐ๋ค๋ฆฌ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์๋ค. ์ด๋ฐ ์ํ์ ๋๋ฌํ์ ๋, ์ด๋ค ํ๋ก์ธ์ค๋ค์ deadlock์ด๋ผ๊ณ ํ๋ค.
- ์ฆ, ๋ ๊ฐ ์ด์์ ํ๋ก์ธ์ค๊ฐ ๋๊ธฐ ์ค์ธ ํ๋ก์ธ์ค ์ค ํ๋๋ก ์ธํด ๋ฐ์ํ ์ ์๋ ์ด๋ฒคํธ๋ฅผ ๋ฌดํ์ ๋๊ธฐํ๊ณ ์๋ ์ํฉ์ด๋ค.
- ์ด๋ "์ด๋ฒคํธ"๋, mutex lock๊ณผ Semaphore๊ฐ์ Resource์ ํ๋๊ณผ ๋ฐฉ์ถ์ด๋ค.
- Starvation (infinite blocking)
- Semaphore์์ ํ ํ๋ก์ธ์ค๊ฐ ๋ฌดํ์ ํ๊ฒ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ ์ํฉ
- ex) waiting list is implemented by LIFO order
- Priority inversion(์ฐ์ ์์ ์ญ์ )
- ๋์ ์ฐ์ ์์ ํ๋ก์ธ์ค๊ฐ ํ์ฌ ๋ฎ์ ์ฐ์ ์์ ํ๋ก์ธ์ค ๋๋ ์ฐ์๋ ๋ฎ์ ์ฐ์ ์์ ํ๋ก์ธ์ค๋ค์ ์ํด ์ ๊ทผ๋๊ณ ์๋ ์ปค๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ๋ณ๊ฒฝํ ํ์๊ฐ ์์ ๋ ์ค์ผ์ค๋ง์ ์ด๋ ค์์ด ์๊ธฐ๊ฒ ๋๋ค.
- ์ปค๋๋ฐ์ดํฐ๋ ๋ฝ์ ์ํด ๋ณดํธ๋๊ธฐ ๋๋ฌธ์ ๋ฎ์ ์ฐ์ ์์ ํ๋ก์ธ์ค๊ฐ ์์์ ์ฌ์ฉ์ ๋ง์น ๋๊น์ง ๋์ ์ฐ์ ์์ ํ๋ก์ธ์ค๊ฐ ๊ธฐ๋ค๋ ค์ผ ํ๋ค. ๋ฎ์ ์ฐ์ ์์ ํ๋ก์ธ์ค๊ฐ ๋ ๋ค๋ฅธ ๋์ ์ฐ์ ์์ ํ๋ก์ธ์ค์ ์ํด ์ ์ ๋๋ ๊ฒฝ์ฐ์ ์ํฉ์ ๋์ฑ ๋ณต์กํด์ง๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ ๋ฎ์ ์ฐ์ ์์ ํ๋ก์ธ์ค๋ ๊ณ์ ๊ธฐ๋ค๋ ค์ผ๋ง ํ๋ค.
- ์์**
- L, M, H ์ธ ๊ฐ์ process๊ฐ ์กด์ฌ
- ์ฐ์ ์์๋ L < M < H
- H๋ L์ ์ํด Semaphore S๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค.
- L์ M์ ๊ธฐ๋ค๋ ค์ผ ํ๋ค. ๊ทธ๊ฒ์ ๋ฎ์ ์ฐ์ ์์ ๋๋ฌธ์
- ๋ฐ๋ผ์ H๋ M์ ๊ธฐ๋ค๋ฆฐ๋ค.
'CS > Operating System' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Operating System] ์ด์์ฒด์ Caching [2] (0) | 2024.03.09 |
---|---|
[Operating System] ์ด์์ฒด์ Caching [1] (0) | 2024.03.07 |
[์ด์์ฒด์ ] Chapter7. Synchronization Examples (0) | 2022.06.01 |