reference: kocw์ ๋ฐํจ๊ฒฝ ๊ต์๋ ๊ฐ์์ ๊ถ์ง์ฑ ๊ต์๋ ๊ฐ์(๋ํ ์ ๊ท ์์
)
์์
์ ๋ฃ๊ณ ๋์ ๊ฐ์ ๊ต์ฌ๋ฅผ ํ์ดํํ๊ณ ํ๊ธฐํ ๋ถ๋ถ์ ์ถ๊ฐ์ ์ผ๋ก ์ ๋ฆฌํ์์ต๋๋ค.
์น๋ทฐ์์ toc๋ฅผ ์ ๊ณตํฉ๋๋ค.
github์ md ํ์ผ๋ก ๋ณด๋ ๊ฒ ํธํ์๋ค๋ฉด, ์ฌ๊ธฐ๋ก ์ด๋ํด์ฃผ์๋ฉด ๋ฉ๋๋ค.
1 Race Condition๋?
์ปดํจํฐ์์ ์ฐ์ฐ์ ํ ๋๋ ํญ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์์ ์ฐ์ฐํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ด๋๊ฐ ์ ์ฅํด๋๋๋ก ๋์ด์๋ค.
race condition์ด๋ ํ๋์ ๊ณต์ data์ ์ฌ๋ฟ์ด ์ ๊ทผํ๋ ค๊ณ ํ ๋, ์ฆ ์ฐ์ฐํ ์ ์๋ ์ฃผ์ฒด๊ฐ ์ฌ๋ฌ ๊ฐ์ผ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋งํ๋ค.
Storage-box๋ฅผ ๊ณต์ ํ๋ E-box๊ฐ ์ฌ๋ฟ ์๋ ๊ฒฝ์ฐ, race condition์ ๊ฐ๋ฅ์ฑ์ด ์๋ค.
Storage-box : Execution-box์ ๊ด๊ณ๋
๋ฉ๋ชจ๋ฆฌ : CPU(multiprocessor system),
Address Space : Process ์์ ์ฑ๋ฆฝํ ์ ์๋ค.
2 ์ธ์ race condition์ด ๋ฐ์ํด?
(2-0. ๊ณตํต์ ์ผ๋ก...)
Q. ํ๋ก์ธ์ค๋ค ๊ฐ์๋ ๊ฑฐ์, ์ผ๋ฐ์ ์ผ๋ก ์ฃผ์ ๊ณต๊ฐ์ ๊ณต์ ํ์ง ์๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ธ์ race condition ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊น?
A. ๊ณตํต์ ์ผ๋ก ์ด์์ฒด์ ์ ๋ค์ด๊ฐ์ ์์ ์ ์ฒ๋ฆฌํ ๋ ๋ฐ์ํ๋ค. ์ด์์ฒด์ ์์ ์์ ์ ํ๋ฉด ์ผ์ข ์ ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฒ ๋๊ธฐ ๋๋ฌธ์ด๋ค.
์กฐ๊ธ ๋ ์์ธํ ์ดํด๋ณด๊ฒ ๋ค.
2-1. kernal ์ํ ์ค interrupt ๋ฐ์ ์
์ปค๋(OS) ๋ชจ๋์์ ์ํ ์ค(running)์ธ๋ฐ ๋ ๊ธด๊ธํ, ์ค์ํ interrupt๊ฐ ๋ฐ์ํ์ฌ interrupt ์ฒ๋ฆฌ ๋ฃจํด์ด ์ํํ๋๋ก cpu๋ฅผ ๋๊ธธ ๋์ด๋ค.
์์ชฝ ๋ค ์ปค๋ ์ฝ๋์ด๋ฏ๋ก kernal address space๋ฅผ ๊ณต์ ํ๋ค.
์ ์ฌ์ง์ ๊ฒฝ์ฐ, count ๊ฐ์ ์ ์ register์ count ๊ฐ์ ์ฝ์ด๋ค์๊ธฐ์ ๊ฐ์ ์ฐ์ฐ์ ๋ฐ์๋์ง ์์ ๊ฒ์ด๋ค.
Q. ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น?
A. count ๋ณ์๋ฅผ ๊ฑด๋๋ฆฌ๊ธฐ ์ ์ interrupt disable ์์ผ๋๋ค (= ๋ณ์ ๊ฑด๋๋ฆฌ๋ ๋์ค์๋ interrupt๋ฅผ ๋ฐ์ง ์๊ฒ ๋ค.) ์ผ๋ฐ์ ์ธ ์์คํ ์์๋ ๋ถ๊ณผ instruction ํ ๋๊ฐ ๋ ์ฒ๋ฆฌํ๋ ๋์์ ๋ฌธ์ ๊ฐ ์๊ธธ๋งํผ ๊ธด๊ธํ ์ผ์ ๋ฐ์ํ์ง ์๋๋ค.
2-2. Process ๊ฐ system call์ ํ์ฌ kernal mode ๋ก ์ํ ์ค์ธ๋ฐ context switch๊ฐ ์ผ์ด๋๋ ๊ฒฝ์ฐ
ํ๋ก์ธ์ค A์ B ๋ ๊ฐ๊ฐ์ ์ฃผ์ ๊ณค๊ฐ์ ์ฌ์ฉํ๊ธฐ์ data sharing์ด ์๋ค. ํ์ง๋ง system call์ ํ๋ ๋์์๋ kernal address space์ data๋ฅผ accessํ๊ฒ ๋๋ค. ์ฆ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๊ฒ ๋๋ค. ์ด ์์ ์ค๊ฐ์ cpu๋ฅผ ๋นผ์๊ธฐ๊ฒ ๋๋ฉด race condition์ด ๋ฐ์ํ๋ค.
๋ ์์ธํ ๊ทธ๋ฆผ์ ์ค๋ช ํ์๋ฉด, ํ๋ก์ธ์ค A์ ํ ๋น ์๊ฐ์ด ๋๋ B์๊ฒ ๋์ด๊ฐ๋ฉด์ context switch๊ฐ ๋ฐ์ํ๋ค. ํ์ฌ ๋ฌธ๋งฅ์ ์ ์ฅํ๊ฒ ๋๋๋ฐ, ์ด ๋ count์ ๊ฐ์ ์ด๋ฏธ cpu์์ register๋ก ์ฝ์ด๋ค์๋ค. ์ดํ ํ๋ก์ธ์ค B์์ count++ ์ฐ์ฐ์ ํ์ง๋ง, ๋ค์ A๋ก ๋ฌธ๋งฅ ๊ตํ์ด ์ผ์ด๋ ๋ B ์์ ์ด์ ์ count ๊ฐ์ด register์ ์ ์ฅ๋์ด ์๊ณ ์ด ๊ฐ์ผ๋ก ์ด์ด์ ++์ ์ฐ์ฐ์ ํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก B์ ์์ ์ ์ ์ฉ์ด ๋์ง ์๋๋ค. 2๋ฒ์ด ์๋ 1๋ฒ๋ง count ๊ฐ์ด ์ฆ๊ฐํ๋ค.
Q. ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น?
A. ์ปค๋ ๋ชจ๋์์ ์ํ ์ค์ผ ๋๋ CPU๋ฅผ ๋นผ์์ง ๋ชปํ๋๋ก ํ๋ค.
2-3. Multiprocessor์์ shared memory ๋ด์ kernal data
Q. ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น?
ํด๊ฒฐ ๋ฐฉ๋ฒ 1. ํ๋ฒ์ํ๋์ cpu๋ง์ด ์ปค๋์ ๋ค์ด๊ฐ ์ ์๊ฒ ํ๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด์ง๋ง ๊ต์ฅํ ํฐ overhead๋ฅผ ๋ฐ์์ํจ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ 2. ์ปค๋ ๋ด๋ถ์ ์๋ ๊ฐ ๊ณต์ ๋ฐ์ดํฐ์ ์ ๊ทผํ ๋๋ง๋ค ๋ฐ์ดํฐ ๊ฐ๊ฐ์ ๋ํด lock/unlock์ ํ๋ค.
3 ๋๊ธฐํ ๋ฌธ์ ์ SOL: Algorithm
3-0. ํ๋ก๊ทธ๋จ์ ํด๊ฒฐ๋ฒ์ ์ถฉ์กฑ ์กฐ๊ฑด
๊ฐ์ : ๋ชจ๋ ํ๋ก์ธ์ค์ ์ํ ์๋๋ 0๋ณด๋ค ํฌ๋ค, ํ๋ก์ธ์ค๋ค ๊ฐ์ ์๋์ ์ธ ์ํ ์๋๋ ๊ฐ์ ํ์ง ์๋๋ค.
- Mutual Exclusion(์ํธ ๋ฐฐ์ ) ํ๋ก์ธ์ค Pi๊ฐ critical section ๋ถ๋ถ์ ์ํ ์ค์ด๋ฉด ๋ค๋ฅธ ๋ชจ๋ ํ๋ก์ธ์ค๋ค์ ๊ทธ๋ค์ critical section์ ๋ค์ด๊ฐ๋ฉด ์ ๋๋ค.
- Progress(์งํ) ์๋ฌด๋ critical section์ ์์ง ์์ ์ํ์์ critical section์ ๋ค์ด๊ฐ๊ณ ์ ํ๋ ํ๋ก์ธ์ค๊ฐ ์์ผ๋ฉด critical section์ ๋ค์ด๊ฐ๊ฒ ํด์ฃผ์ด์ผ ํ๋ค.
- Bounded Waiting(์ ํ ๋๊ธฐ) ํ๋ก์ธ์ค๊ฐ cricical section์ ๋ค์ด๊ฐ๋ ค๊ณ ์์ฒญํ ํ๋ถํฐ ๊ทธ ์์ฒญ์ด ํ์ฉ๋ ๋๊น์ง ๋ค๋ฅธ ํ๋ก์ธ์ค๋ค์ด critical section์ ๋ค์ด๊ฐ๋ ํ์์ ํ๊ณ๊ฐ ์์ด์ผ ํ๋ค. ์ด ๋ง์ starvation์ ๋ง์์ผ ํ๋ค ๋ ๋ป์ธ๋ฐ, ์ฌ๋ฟ์ด critical section์ ๋ค์ด๊ฐ๊ณ ์ถ์ด์ ๊ฒฝํฉ์ด ์ผ์ด๋ ์ํ์์ ์ค๋ช ํ๋ ๋ง์ด๋ค.
๐critical section: ๊ฐ ํ๋ก์ธ์ค์ code segment ์ค ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ทผํ๋ ์ฝ๋
3-1. ์ต์ด์ ์๋
์๋์ ์ฝ๋๋ ํ๋ก์ธ์ค๋ค์ ์ผ๋ฐ์ ์ธ ๊ตฌ์กฐ๋ก, ํ๋ก์ธ์ค๋ค์ ์ํ์ ๋๊ธฐํ๋ฅผ ์ํด ๋ช๋ช ๋ณ์๋ฅผ ๊ณต์ ํ ์ ์๋ค → synchronization variable
do {
entry section
critical section // ์ ๋ค๋ก cs ์ ๊ทผ ๋์ค์ ๋๊ธฐ์ง ์๋๋ก ์กฐ์น๋ฅผ ์ทจํจ.
exit section
remainder section
} while (1);
3-2. Algorithm 1
- Synchronization variable
- int turn;
- initially turn = 0; => Pi can enter its critical
do {
while (turn != 0); /* My turn? */
critical section // ๋ด ์ฐจ๋ก๋ฉด ๊ณต์ ์ฝ๋ ์ํ
turn = 1: /* Now it’s your turn ์๋๋ฐฉ ์ฐจ๋ก๋ก ๋ฐ๊ฟ */
remainder section
} while (1);
// ๋ด ์ฐจ๋ก๋ฉด ๊ณต์ ์ฝ๋ ์ํ
// ์๋๋ฐฉ ์ฐจ๋ก๋ก ๋ฐ๊ฟ
Satisfies mutual exclusion, but not progress
์ฆ, ๊ณผ์๋ณดํธ: ๋ฐ๋์ ํ๋ฒ์ฉ ๊ต๋๋ก ๋ค์ด๊ฐ์ผ๋ง ํจ(swap-turn) ์๋๋ฐฉ์ด turn์ ๋ด ๊ฐ์ผ๋ก ๋ฐ๊ฟ์ค์ผ๋ง ๋ด๊ฐ ๋ค์ด๊ฐ ์ ์์
Q. ํน์ ํ๋ก์ธ์ค๊ฐ ๋ ๋น๋ฒํ cs์ ๋ค์ด๊ฐ์ผ ํ๋ค๋ฉด?
A. ์ฐจ๋ก๋ฅผ ๋์๊ฐ๋ฉฐ ์ฃผ๋ ์๊ณ ๋ฆฌ์ฆ์ด๊ธฐ์ ๋ ์์ฃผ cs์ ๋ค์ด๊ฐ๋ ํ๋ก์ธ์ค๋ ์๋๋ฐฉ์ด cs๋ฅผ ํ์ง ์์ผ๋ฉด ์งํ์ด ๋์ง ์๋๋ค.
3-3. Algorithm 2
- Synchronization variable
- boolean flag[2]; initially flag [๋ชจ๋] = false; //no one is in CS
- if (flag [i] == true): "Pi ready to enter its critical section"
do {
flag[i] = true; /* Pretend I am in */
while (flag[j]); /* ts he also in? then wait, ์๋๋ฐฉ ๊น๋ฐ์ด ๋ด๋ ค๊ฐ๋ฉด */
critical section // ๋ ์ํ
flag [i] = false; /* I am out now, ๋์ฌ ๋ ๊น๋ฐ ๋ด๋ฆผ */
remainder section
) while (1);
// ๋ ์ํ
// ๋์ฌ ๋ ๋ด ๊น๋ฐ ๋ด๋ฆผ(= ๋ ํ์์์ด)
๋ด(i)๊ฐ ๊น๋ฐ๋ง ๋ค๊ณ (while ๋ฌธ ์ด์ ๊น์ง ์ํํ๊ณ ) CPU๋ฅผ ๋นผ์๊น
์๋๋ฐฉ์ด CPU๋ฅผ ์ป์ด ์๋๋ฐฉ(j)๋ ๊น๋ฐ์ ๋ค๊ณ ๋ค์ CPU๋ฅผ ๋นผ์์.
๋(i)๋ ์๋๋ฐฉ(j)์ ํ์ธํ๋๋ฐ ๊น๋ฐ์ด ๋ค๋ ค์์
→ ๋ ๋ค 2ํ๊น์ง ์ํ ํ ๋์์์ด ์๋ณดํ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์๋ค.
Satisfies mutual exclusion, but not progress requirement.
3-4. Algorithm 3
Algorithm 3 (Peterson's Algorithm)
do {
flag[i] = true; /* My intention is to enter .... - ์์ฌ ํํ */
turn = j; /* Set to his(์๋๋ฐฉ) turn */
while (flag[j] && turn==j); /* ๊ธฐ๋ค๋ ค only if ...*/
critical section // ์๋๋ฐฉ์ด ๊น๋ฐ์ ๋ค์ง ์์๊ฑฐ๋ ๋ค์์ง๋ง ๋ด turn์ธ ๊ฒฝ์ฐ ์ํ๋จ
flag[i] = false; // ๋ ์ด์ ๋ ์์จ
remainder section
} while (1);
Meets all three requirements solves the critical section problem for two processes.
but Busy Waiting! (=spin lock, ๊ณ์ CPU์ memory๋ฅผ ์ฐ๋ฉด์(์์๋ญ๋น) wait)
busy waiting์ ๋ค์์ ๋ ์์ธํ ์ค๋ช
4 ๋๊ธฐํ ๋ฌธ์ ์ SOL: Semaphores
4-0. Synchronization Hardware
ํ๋์จ์ด์ ์ผ๋ก Test & modify๋ฅผ Atomicํ๊ฒ ์ํํ ์ ์๋๋ก ์ง์ํ๋ ๊ฒฝ์ฐ ์์ ๋ฌธ์ ๋ ๊ฐ๋จํ๊ฒ ํด๊ฒฐ๊ฐ๋ฅ
* atomicํ๋ค: ์ค๊ฐ์ cpu๋ฅผ ๋นผ์๊ธฐ๊ฑฐ๋ ์ชผ๊ฐ์ง ์ ์๊ณ , ์ฝ์ด๊ฐ๋ ๊ฒ๊ณผ data๋ฅผ ๋ฐ๊ฟ ์ ์ฅํ๋ ๊ฒ์ ํ๊บผ๋ฒ์ ๋ฐ๋์ ์คํํจ
Synchronization variable:
boolean lock = false; // ์์ง ์๋ฌด๋ cs์ ๋ค์ด๊ฐ์ง ์์
do {
while(Test_and_Set(lock)); // lock์ ๊ฐ์ ์ฝ๊ณ true๋ก ์ค์
critical section
lock = false;
remainder section
}
→ ์ด๋ฌํ ์์ ๋ค์ ์ถ์ํ ์ํจ ๊ฒ์ด Semaphores
4-1. Semaphores
์๊ณผ ๊ฐ์ด synchronization ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ํ๋์จ์ด ์ ์ผ๋ก ๊ตฌํ๋์ด ์๋ค๊ณ ๊ฐ์ ํ๊ณ ์ด๋ฅผ ํ๋ก๊ทธ๋๋ฐ ํ ์ ์๋๋ก ์ง์ํ๋ ์ถ์ ์๋ฃํ.
์ธ๋งํฌ๊ฐ ์ง์๋๋ฉด ํ๋ก๊ทธ๋๋จธ๋ ๋๋จํ ํจ์จ์ ์ผ๋ก synchronize ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค.
Semaphore S
- Integer Variable (์์์ ๊ฐ์)
- ์๋์ ๋๊ฐ์ง Atomic ์ฐ์ฐ์ ์ํด์๋ง ์ ๊ทผ ๊ฐ๋ฅ
๊ณต์ data ํ๋ ๊ณผ์
P(S):
while (S<=0) do no-op; // 5๊ฐ ์ด๋ฏธ ์ฌ์ฉํ๊ณ ์๋ค๋ฉด ๊ธฐ๋ค๋ฆผ
S--;
๊ณต์ data ๋ฐ๋ฉ ๊ณผ์
V(S):
S++; // ํ ๊ฐ์ ์์์ ๋ด์ด๋์.
์ด๋ก์จ (ํ๋์ ํ๋ก์ธ์ค๋ง ์ด ๊ณต์ data์ ์ ๊ทผํ ์ ์๋) mutual exclusion ๋ฌธ์ ๋ฅผ ํ ์ ์์.
4-2. busy wait
semaphore mutex; // mutex: mutual exclusion์ ์ค๋ง, 1๋ก ์ด๊ธฐํ (1๊ฐ๊ฐ CS์ ๋ค์ด๊ฐ ์ ์๋ค๋ ๋ป)
Process Pi
do {
P(mutex); // ์์๋ฉด ๋ค์ด๊ฐ๊ณ ์๋๋ฉด ๊ณ์ํด์ ๊ธฐ๋ค๋ฆผ.
critical section
V(mutex);
remainder section
} while (1);
ํ์ง๋ง busy wait (=spin lock)์ ํจ์จ์ ์ด์ง ๋ชปํจ.
spin lock์ ์ํฉ: ๋ง์ฝ ๋๊ตฐ๊ฐ cs์ ๋ค์ด๊ฐ ์์ด์ mutex ๊ฐ์ด 0์ด๋ฉด P ์ฐ์ฐ์ ๋น ์ ธ๋๊ฐ์ง ๋ชปํ๋ค. ๋ค๋ฅธ ์น๊ตฌ๊ฐ cs๋ฅผ ๋น ์ ธ๋๊ฐ๋ฉด์ V์ฐ์ฐ์ ํตํด mutex๊ฐ์ 1๋ก ๋ณต์์ํค๊ธฐ ์ ๊น์ง๋ while๋ฌธ๋ง ๋๋ฆฌ๋ฉด์ ์ธ๋ฐ์์ด CPU๋ฅผ ๋ญ๋นํ๋ค.
4-3. block and wakeup
semaphore์ด ๋ค์๊ณผ ์ ์๋จ
// 1. ์ธ๋งํฌ์ ์ ์
typedef struct
{
int value; // semaphore
struct process *L; // process wait queue
}semaphore;
// 2. ์ธ๋งํฌ์ ์ฐ์ฐ ์ ์
P(S):
S.value--; // ์ผ๋จ -1 !!! ๋ค์ด๊ฐ ์ค๋น๋ฅผ ํจ
if (S.value < 0) { // ์ฌ๋ถ์ด ์๋ค๋ฉด
add this process to S.L; // wait queue์ ๋ฃ๊ณ
block(); // ์ ๋ค๊ฒ ํจ
}
V(S):
S.value++; // ์ผ๋จ +1 !!! ํ ๊ฐ์ ์์์ ๋ด์ด๋์ ์ค๋น๋ฅผ ํจ.
if (S.value <= 0) { // ๋๊ตฐ๊ฐ ์ ๋ค์ด ์๋ค๋ฉด
remove a process P from S.L; // ๋์ง์ด๋ด์
wakeup(P); // ๊นจ์
}
block ๊ณผ wakeup์ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ์
- block: ์ปค๋์ block์ ํธ์ถํ ํ๋ก์ธ์ค๋ฅผ suspend์ํด, ์ด ํ๋ก์ธ์ค์ PCB๋ฅผ semaphore์ ๋ํ wait queue์ ๋ฃ์
- wakeup(P): block๋ ํ๋ก์ธ์ค P๋ฅผ wakeup์ํด, ์ด ํ๋ก์ธ์ค์ PCB๋ฅผ ready queue๋ก ์ฎ๊น
์์ value์๋ ๋ค๋ฅด๋ค. ์ฌ๋ถ์ ๊ฐ์๋ฅผ ์ธ๋ ๊ฒ์ด ์๋๋ค.
0 ์ดํ์ ๊ฐ์ ์์์ ์ฌ๋ถ์ด ์์ด์ ๋๊ตฐ๊ฐ ์ ๋ค์ด์๋ค๋ ๋ป์ด๊ณ ์์๋ ์์์ด ๋จ์๋๊ณ ์๋ค๋ ๋ป์ด๋ค.
4-4. Busy-wait vs Block/wakeup
Q. ๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๊ฒ ๋ ๋์? Busy-wait vs Block/wakeup
A. ์ผ๋ฐ์ ์ผ๋ก๋ Block/wakeup ๋ฐฉ์์ด ๋ ์ข์.
Critical section์ ๊ธธ์ด๊ฐ ๊ธด ๊ฒฝ์ฐ (๋๋ cs์ ๊ฒฝํฉ(๊ฒฝ์)์ด ๋์์๋ก) Block/wakeup ๋ฐฉ์์ด ์ ๋นํด. ํ์ง๋ง ๋ฐ๋์ธ ๊ฒฝ์ฐ์๋ Block/wakeup ๋ฐฉ์์ ์ค๋ฒํค๋๊ฐ Busy-wait ์ค๋ฒํค๋๋ณด๋ค ๋ ์ปค์ง ์ ์์ด.
4-5. semaphores๋ 2๊ฐ์ ํ์ ์ผ๋ก ๋ถ๋ฅํ ์ ์๋ค.
- counting semaphore
- ๋๋ฉ์ธ์ด 0์ด ์ด์์ธ ์์์ ์ ์๊ฐ
- ์ฃผ๋ก resource counting ์ ์ฌ์ฉ - ์์์ ๊ฐ์๋ฅผ ์
- binary semaphore (=mutex)
- 0 ๋๋ 1์ ๊ฐ๋ง ๊ฐ์ง ์ ์๋ semaphore
- ์ฃผ๋ก mutual exclusion (lock/unlock)์ ์ฌ์ฉ
4-6. ์ฉ์ด ์ ๋ฆฌ: Deadlock and Starvation
Deadlock
- ๋ ์ด์์ ํ๋ก์ธ์ค๊ฐ ์๋ก ์๋๋ฐฉ์ ์ํด ์ถฉ์กฑ๋ ์ ์๋ event๋ฅผ ๋ฌดํํ ๊ธฐ๋ค๋ฆฌ๋ ํ์
Starvation
- Infinite blocking : ํ๋ก์ธ์ค๊ฐ suspend๋ ์ด์ ์ ํด๋น๋๋ ์ธ๋งํฌ์ด ํ์์ ๋น ์ ธ๋๊ฐ ์ ์๋ ํ์
5 ๋๊ธฐํ์ ๊ณ ์ ์ ์ธ ๋ฌธ์
5-1. Bounded-Buffer Problem (Producer-Consumer Problem)
- Shared data
- buffer ์์ฒด ๋ฐ buffer ์กฐ์ ๋ณ์ (empty, full buffer์ ์์ ์์น)
- Synchronization variables
- mutual exclusion
- binary semaphore
- shared data์ mutual exclusion(lock/unlock)์ ์ํด
- resource count
- integer(counting) semaphore
- ๋จ์ full/empty buffer์ ์๋ฅผ ํ์ํ๊ธฐ ์ํด
- mutual exclusion
์ฝ๋
- Synchronization variables
- semaphore full = 0, empty = n, mutex = 1;
Producer
do{ ...
produce an item in x
P(empty); // ๋น ๋ฒํผ๋ฅผ ์ป๋ ๊ณผ์ , ๋ง์ฝ ์๋ค๋ฉด ์๋ฐ์๊ฐ ๋ํ๋์ ๋น ๋ฒํผ๋ฅผ ๋ง๋ค์ด์ค ๋๊น์ง ๊ธฐ๋ค๋ฆผ
P(mutex); // lock
...
add x to buffer
...
V(mutex); // unlock
V(full); // ๋ด์ฉ ์ฐฌ ๋ฒํผ ์ถ๊ฐ, ํน์ ์๋น์๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์์๋ค๋ฉด ๊นจ์์ ์๋นํ ์ ์๋๋ก
} while (1);
-----------------------------------------------------------------------
Consumer
do {
P(full); // ๋ด์ฉ์ด ๋ค์ด์๋ ๋ฒํผ ํ๋
P(mutex); // ๊ณต์ data lock
...
remove anitem from buffer to y
...
V(mutex);
V(empty); // ๋น ๋ฒํผ ์ถ๊ฐ, ํน์ ์์ฐ์๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์์๋ค๋ฉด ๊นจ์์ ์์ฐํ ์ ์๋๋ก
...
consume the item in y
...
} while (1);
์์ฝํ์๋ฉด,
์์ฐ์ ํ๋ก์ธ์ค์ ์๋น์ ํ๋ก์ธ์ค๊ฐ ์๋๋ฐ ๊ณต์ ๋ฒํผ์ ๋์ ์ ๊ทผ ์ ๋ฌธ์ ๋ฐ์ ๋ฒํผ์ ๋ํด ๋ฝ์ ๊ฑฐ๋ semaphore๋ฅผ ์ฌ์ฉํ๊ณ ์์์ ์ ์ฅ์์์ ์์์ธ ๋น ๋ฒํผ์ ์๋น์ ์ ์ฅ์์์ ์์์ธ ๋ด์ฉ์ด ๋ ๋ฒํผ๋ฅผ ์นด์ดํ ํ๊ธฐ ์ํด์ ์นด์ดํ semaphore ๋ฅผ ์ฌ์ฉํ๋ค.
5-2. Readers-Writers Problem
- ํ process๊ฐ db์ write ์ค์ผ ๋ ๋ค๋ฅธ process๊ฐ ์ ๊ทผํ๋ฉด ์๋จ
- read๋ ๋์์ ์ฌ๋ฟ์ด ํด๋ ๋จ
- solution
- writer๊ฐ db์ ์ ๊ทผ ํ๊ฐ๋ฅผ ์์ง ์ป์ง ๋ชปํ ์ํ์์๋ ๋ชจ๋ ๋๊ธฐ ์ค์ธ reader๋ค์ ๋ค db์ ์ ๊ทผํ๊ฒ ํด์ค๋ค.
- writer๋ ๋๊ธฐ ์ค์ธ reader๊ฐ ํ๋๋ ์์ ๋ db ์ ๊ทผ์ด ํ์ฉ๋๋ค.
- ์ผ๋จ writer๊ฐ db ์ ๊ทผ ์ค์ด๋ฉด reader๋ค์ ์ ๊ทผ์ด ๊ธ์ง๋๋ค.
- wrtier๊ฐ db์์ ๋น ์ ธ๋๊ฐ์ผ์ง๋ง reader์ ์ ๊ทผ์ด ํ์ฉ๋๋ค.
- Shared data
- DB ์์ฒด
- readcount : ํ์ฌ db์ ์ ๊ทผ ์ค์ธ reader์ ์
- Synchronization variables
- mutex: ๊ณต์ ๋ณ์ readcount๋ฅผ ์ ๊ทผํ๋ ์ฝ๋(cs)์ mutual exclusion ๋ณด์ฅ์ ์ํด
- db: reader์ wirter๊ฐ ๊ณต์ db ์์ฒด ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๊ทผํ๊ฒ ํ๋ ์ญํ
// Shared data๋
int readcount = 0;
DB ์์ฒด;
// Synchronization variables๋
semaphore mutex = 1, db = 1;
------------------------------------------------------------------------
Writer // ๋จ์ํจ.
P(db);
...
writing DB is performed
...
V(db);
------------------------------------------------------------------------
Reader
P(mutex); // readcount๋ผ๋ ๊ณต์ ๋ณ์์ ์ ๊ทผํ๊ธฐ ์ ์ lock
readcount++;
if (readcount == 1) P(db); // reader๊ฐ ์ฝ๊ธฐ ์ ์ writer๊ฐ ์ฐ์ง ๋ชปํ๋๋ก db๋ฅผ lock
V(mutex); // readcount๋ผ๋ ๊ณต์ ๋ณ์ unlock
...
reading DB is performed
...
P(mutex);
readcount--;
if (readcount == 0) V(db); // reader๊ฐ ์ฝ์๊ธฐ์ writer๊ฐ ์ธ ์ ์๋๋ก db๋ฅผ unlock
V(mutex);
5-3. Dining-Philosophers Problem
๋ํ์ ์ธ ๊ต์ฐฉ์ํ (Dead Lock) ๋ฌธ์ ์ด๋ค.
// Synchronization variables๋
semaphore chopstick[5];
/* Initially all values are 1 */
Philosopher i
do {
P(chopstick[i]);
P(chopstick[(i+1) % 5]);
...
eat();
...
V(chopstick[i]);
V(chopstick[(i+1) % 5]);
...
think();
...
} while (1);
- ์์ solution์ ๋ฌธ์ ์
- deadlock ๊ฐ๋ฅ์ฑ์ด ์๋ค
- ๋ชจ๋ ์ฒ ํ์๊ฐ ๋์์ ๋ฐฐ๊ฐ ๊ณ ํ์ ธ ์ผ์ชฝ ์ ๊ฐ๋ฝ์ ์ง์ด๋ฒ๋ฆฐ ๊ฒฝ์ฐ
- ํด๊ฒฐ ๋ฐฉ์
- 4 ๋ช ์ ์ฒ ํ์๋ง์ด ํ ์ด๋ธ์ ๋์์ ์์ ์ ์๋๋ก ํ๋ค
- ์ ๊ฐ๋ฝ์ ๋ ๊ฐ ๋ชจ๋ ์ง์ ์ ์์ ๋์๋ง ์ ๊ฐ๋ฝ์ ์ง์ ์ ์๊ฒ ํ๋ค
- ๋น๋์นญ: ์ง์(ํ์) ์ฒ ํ์๋ ์ผ์ชฝ (์ค๋ฅธ์ชฝ) ์ ๊ฐ๋ฝ๋ถํฐ ์ง๋๋ก
enum {thinking, hungry, eating} state[5];
semaphore self[5] = 0;
semaphore mutex = 1;
void test (int i) {
if (state[(i+4)%5] != eating && state[i] == hungry && state[(i+1)% 5] != eating) {
state[i] = eating;
V(self[i]);
}
void putdown(int i) {
P(mutex);
state[i] = thinking;
test((i+4) % 5);
test((i+1) % 5);
V(mutex);
}
void pickup(int i) {
P(mutex);
state[i] = hungry;
test(i);
V(mutex);
P(self[i]);
}
Philosopher i
do{
pickup(i);
eat();
putdown(i);
think();
} while(1);
6 ๋๊ธฐํ ๋ฌธ์ ์ SOL: Monitor
6-0. ๋ฑ์ฅ ๋ฐฐ๊ฒฝ: Semaphore์ ๋ฌธ์ ์
- ์ฝ๋ฉํ๊ธฐ ํ๋ค๋ค
- ์ ํ์ฑ(correctness)์ ๊ฒ์ฆ, ์ ์ฆ์ด ์ด๋ ต๋ค
- ์๋ฐ์ ํ๋ ฅ(voluntary cooperation)์ด ํ์ํ๋ค
- ํ๋ฒ์ ์ค์๊ฐ ๋ชจ๋ ์์คํ ์ ์น๋ช ์ ์ธ ์ํฅ์ ์ค๋ค.
→ process ๋๊ธฐํ ๋ฌธ์ ๋ฅผ ๋ ์ฝ๊ฒ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ monitor
6-1. Monitor
๋์ ์ํ์ค์ธ ํ๋ก์ธ์ค ์ฌ์ด์์ ์ถ์ํ ๋ฐ์ดํฐ ํ์ ์ ์์ ํ ๊ณต์ ๋ฅผ ๋ณด์ฅํ๊ธฐ ์ํ high-level synchronization constructor
์ฝ๊ฒ ๋งํด, ๊ณต์ data์ ๋์ ์ ๊ทผ ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฑด๋ฐ, ์ด ๊ณต์ data๋ฅผ ๋ชจ๋ํฐ ์์ ์ ์ํด์ฃผ๊ณ ์ ๊ทผ์ ๋ชจ๋ํฐ ์์ ์ฝ๋ ์ฐ์ฐ๋ง์ผ๋ก ๊ฐ๋ฅํ๊ฒ ํ๋ค. ๊ณ ๊ธ ์ธ์ด ํ๋ก๊ทธ๋๋ฐ ์ฐจ์์์ ๊ตฌํ๋ ๊ฒ์ด๋ค.
- ๋ชจ๋ํฐ ๋ด์์๋ ํ๋ฒ์ ํ๋ก์ธ์ค๋ง์ด ํ๋ ๊ฐ๋ฅ
- ํ๋ก๊ทธ๋๋จธ๊ฐ ๋๊ธฐํ ์ ์ฝ ์กฐ๊ฑด์ ๋ช ์์ ์ผ๋ก ์ฝ๋ฉํ ํ์ ์์ !!
- ํ๋ก์ธ์ค๊ฐ ๋ชจ๋ํฐ ์์์ ๊ธฐ๋ค๋ฆด ์ ์๋๋ก condition variable์ ์ฌ์ฉํ๋ค. ex) condition x, y;
- condition variable์ wait์ signal ์ฐ์ฐ์ ์ํด์๋ง ์ ๊ทผ ํ ์ ์๋ค.
- x.wait();
- x.wait()๋ฅผ invokeํ ํ๋ก์ธ์ค๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ x.signal()์ invokeํ๊ธฐ ์ ๊น์ง suspend๋๋ค.
- ์์์ ์ฌ๋ถ์ด ์์ ๋ blocked queue์ ๊ฐ์ ์ค์ ์๋๋ก ํ๋๋ฐ ์ฆ ์ ๊ทผ๋ค.(blocked)
- x.signal();
- x.signal()์ ์ ํํ๊ฒ ํ๋์ suspend๋ ํ๋ก์ธ์ค๋ฅผ resumeํ๋ค.
- Suspend๋ ํ๋ก์ธ์ค๊ฐ ์์ผ๋ฉด ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์๋๋ค.
- ์์์ ์ฌ๋ถ์ด ์์ ๋ ์ํ๋๋ค.
- x.wait();
์ ๋ฆฌํ์๋ฉด, semaphore๋ ์์์ ์ผ๋ก ์ํํ๋๋ก ํ๋ ๊ฒ์ด์ง๋ง monitor๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋์ ์ ๊ทผ์ ์์ ๋ง๋๋ค. ๋ฐ๋ผ์ ํ๋ก๊ทธ๋๋จธ๋ ๋์ ์ ๊ทผ ๋ฌธ์ ๋ฅผ ์๊ฐํ ํ์๊ฐ ์๋ค. ๊ทธ๋ฅ ๋น ๋ฒํผ๊ฐ ์๋์ง ํ์ธํ ๋ค ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋(์ ๋ค๊ฒ ํ๊ฑฐ๋) ์ํํ๋ฉด ๋๋ค.
6-2. ์์1 - Bounded-buffer proplem (์์ฐ์ ์๋น์ ๋ฌธ์ )
์ฝ๋ฉ ๋ฐฉ๋ฒ
05-1์ ์ฝ๋์ ๋น๊ตํ๋ฉด์ ๋ณด๋ฉด์ ์ฐจ์ด์ ์ ์ง์ค
monitor bounded_buffer {
int buffer[N];
condition full, empty; // ๊ฐ์ ๊ฐ์ง์ง ์๊ณ ์์ ์ ํ์์ ํ๋ก์ธ์ค๋ฅผ sleep ๋๋ signal(๊นจ์ฐ๋) ์ญํ ๋ง ํจ
// ์์ฐ์
void produce (int x) {
if there is no empty buffer
empty.wait(); // ๋น ๋ฒํผ๊ฐ ์์ผ๋ฉด ํ๋ก์ธ์ค๋ ์ ๋ค์ด
add x to an empty buffer; // ๋น ๋ฒํผ๊ฐ ์์ผ๋ฉด ๊ทธ๋ฅ ๋ฐ์ดํฐ ๋ฃ์ผ๋ฉด ๋จ
full.signal(); // ํน์ ์ ๋ค์ด ์์ผ๋ฉด ๊นจ์๋ผ(O), semaphore์ฒ๋ผ condition variable์ ๋ฐ์ํ์ง(X)
}
// ์๋น์
void consume (int* x) {
if there is no full buffer
full.wait(); // ๋ด์ฉ ๋ค์ด์๋ ๋ฒํผ ์์ผ๋ฉด ํ๋ก์ธ์ค๋ (๋ด์ฉ ๋ค์ด์๋ ๋ฒํผ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ํ์ ์ค์์) ์ ๋ค์ด suspend
remove an item from buffer and store it to *x // ์์ผ๋ฉด ๋ด์ฉ ๊บผ๋ด๊ฐ๊ณ
empty.signal(); // ํ๋ก์ธ์ค ๊นจ์
}
}
6-3. ์์2 - Dining Philosophers
์ ๊ฐ๋ฝ: ๊ณต์ data → ์ ๊ทผ์ monitor ์์ ์ ์ํด๋์ด ํด๋น ์ฝ๋๋ก๋ง ์ ๊ทผํ ์ ์๋ค.
/* enter monitor */
monitor dining_philosopher {
enum (thinking, hungry, eating) state[5];
condition self[5];
void pickup(int i) {
state[i] = hungry;
test(i); // ์ ๊ฐ๋ฝ ์ก์ ์ ์๋์ง
if (state[i] != eating)
self[i].wait(); // wait here
}
void putdown(int i) {
state[i] = thinking;
// test left and right neighbors - ๋จน์ ์ ์๋์ง
test((i+4) % 5); // if L is waiting
test((i+1) % 5);
}
void test(int i) {
// if ์ผ์ชฝ๊ณผ ์ค๋ฅธ์ชฝ ๋ชจ๋ ๋ฐฅ์ ์ ๋จน๊ณ ์์ผ๋ฉด
if ((state[(i+4)%5]!=eating) && (state[i]==hungry) && (state[(i+1)%5]!=eating)) {
state[i] = eating;
self[i].signal(); // wake up Pi
}
}
void init() {
for (int i = 0; i < 5; t++)
state[i] = thinking;
}
}
------------------------------------------------------------------------
/* monitor ์ธ๋ถ */
Each Philosopher:
{
pickup(i); // ์ ๊ฐ๋ฝ ์ก๊ธฐ
eat(); // ๋จน๊ฑฐ๋
putdown(); // ๋ด๋ฆผ
think(); // ์๊ฐ
} while(1);
'OS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
9์ฅ Virtual Memory (0) | 2021.06.19 |
---|---|
8์ฅ Memory Management (0) | 2021.06.19 |
7์ฅ Deadlock (0) | 2021.06.19 |
5์ฅ CPU scheduling (0) | 2021.06.18 |
4์ฅ Process Management (0) | 2021.06.18 |
3์ฅ Process (0) | 2021.06.18 |