๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

OS

6์žฅ Process Synchronization

 

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์˜ ์ˆ˜๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด

์ฝ”๋“œ

  • 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๋œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—†์œผ๋ฉด ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š”๋‹ค.
      • ์ž์›์˜ ์—ฌ๋ถ„์ด ์žˆ์„ ๋• ์ˆ˜ํ–‰๋œ๋‹ค.

์ •๋ฆฌํ•˜์ž๋ฉด, 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