Day17 - jeremy0405/Codesquad_CS GitHub Wiki

ํ”„๋กœ์„ธ์Šค ๋™๊ธฐํ™”

Race Condition

๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์—ฐ์‚ฐ์ž(CPU or Process)๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ Race Condition์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์ฝ”๋“œ ์˜์—ญ(Critical-Section)์—์„œ ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋ง๊ฐ€์ง€๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•œ๋‹ค.

OS์—์„œ Race Condition์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ

  1. kernel ์ˆ˜ํ–‰ ์ค‘ ์ธํ„ฐ๋ŸฝํŠธ ๋ฐœ์ƒ ์‹œ
  2. Process๊ฐ€ system call์„ ํ•ด์„œ kernel mode๋กœ ์ˆ˜ํ–‰ ์ค‘์ธ๋ฐ context switch๊ฐ€ ์ผ์–ด๋‚œ ๊ฒฝ์šฐ
  3. Multiprocessor์—์„œ shared memory ๋‚ด์˜ kernel data

์œ„์˜ 1, 2 ์ƒํ™ฉ์—์„œ์˜ Race condition ํ•ด๊ฒฐ๋ฒ•

โ†’ ์ธํ„ฐ๋ŸฝํŠธ๊ฐ€ ๋“ค์–ด ์™€๋„ ์ค‘์š”์ž‘์—…(์ปค๋„์ž‘์—…) ๋๋‚ธ ํ›„์— ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•จ

3 ์ƒํ™ฉ์—์„œ์˜ Race condition ํ•ด๊ฒฐ๋ฒ•

  1. ํ•œ๋ฒˆ์— ํ•˜๋‚˜์˜ CPU๋งŒ ์ปค๋„์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ํ•จ โ†’ ์—„์ฒญ ๋น„ํšจ์œจ์ ์ด๋ผ์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ
  2. ํ•˜๋‚˜์˜ CPU๊ฐ€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•œ ์ƒํƒœ๋ผ๋ฉด lock์„ ๊ฑธ์–ด์„œ ๋‹ค๋ฅธ CPU๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก ํ•จ

Critical section ๋ฌธ์ œ๋ฅผ ํ’€๊ธฐ ์œ„ํ•ด์„œ ๋งŒ์กฑํ•ด์•ผ ํ•  ์กฐ๊ฑด 3๊ฐ€์ง€

  1. Mutual Exclusion (์ƒํ˜ธ ๋ฐฐ์ œ)
    • ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๊ฐ€ critical section์— ๋“ค์–ด๊ฐ€๋ฉด ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋“ค์–ด๊ฐ€์ง€ ๋ชปํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ
  2. Progress
    • ์•„๋ฌด๋„ critical section์— ๋“ค์–ด๊ฐ€ ์žˆ์ง€ ์•Š๋‹ค๋ฉด ๋“ค์–ด๊ฐ€๊ฒŒ ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ๋“ค์–ด๊ฐ€๊ฒŒ ํ—ˆ๋ฝํ•ด์ฃผ๋Š” ๊ฒƒ
  3. Bounded Waiting
    • ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„์ด ์œ ํ•œํ•ด์•ผ ํ•จ (์–ธ์  ๊ฐ€ critical section์— ๋“ค์–ด๊ฐ€๊ฒŒ ํ•ด์ค˜์•ผ ํ•จ)
    • critical section์— ๋“ค์–ด๊ฐ€๊ณ ์ž ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ 3๊ฐœ์ผ ๋•Œ 1 2 ๋ฒˆ ํ”„๋กœ์„ธ์Šค๋งŒ ๊ณ„์† ์™“๋‹ค๊ฐ“๋‹คํ•˜๊ณ  3๋ฒˆ์ด ๋ชป๋“ค์–ด๊ฐ€๋Š” Starvation ํ˜„์ƒ์ด ๋ฐœ์ƒํ•จ

Critical-Section์„ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

  1. int turn์„ ๊ฐ€์ง€๋Š” ๋ฐฉ๋ฒ• โ†’ ์•ž์— ๋“ค์–ด๊ฐ”๋˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ turn์„ ๋‹ค์Œ ํ”„๋กœ์„ธ์Šค ์ฐจ๋ก€๋กค ๋ฐ”๊พธ๊ณ  ๋‚˜๊ฐ€์ฃผ๋ฉด ์ž์‹ ์˜ turn์ด ๋˜๋ฉด ๋“ค์–ด๊ฐ€๋Šฅ ๋ฐฉ์‹์œผ๋กœ Critical-Section์— ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ๋“ค์–ด๊ฐ€๋„๋ก ํ•จ

    โ†’ turn์„ ๋‚ด ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ๋‚ด๊ฐ€ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ โ†’ ์•„๋ฌด๋„ critical section์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์•˜๋‹ค๋ฉด turn์„ ๋ˆ„๊ฐ€ ๋‚ด ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•ด์คŒ?? โ†’ Progress ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•จ

  2. boolean flag[]๋ฅผ ๊ฐ€์ง€๋Š” ๋ฐฉ๋ฒ•

    โ†’ ๋‚ด๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ  ์‹ถ์œผ๋ฉด ์ž์‹ ์˜ flag๋ฐฐ์—ด์„ ture๋กœ ๋งŒ๋“  ์ดํ›„ flag๋ฐฐ์—ด์„ ๋ชจ๋‘ ๋‹ค ๋ณธ ํ›„์— ์ž์‹ ์„ ์ œ์™ธํ•œ ๊ฒƒ๋“ค์ด ๋ชจ๋‘ false์ผ๋•Œ๋งŒ critical section์— ๋“ค์–ด๊ฐ.

    โ†’ ๋งŒ์•ฝ ๋‹ค๋ฅธ์• ๋„ true๋ฅผ ๋“ค๊ณ  ๋™์‹œ์— ๋‚˜๋„ true๋ฅผ ๋“ค๊ฒŒ ๋œ๋‹ค๋ฉด Progress์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•จ

  3. 1, 2 ๋ฐฉ๋ฒ•์„ ์งฌ๋ฝ• int turn๊ณผ boolean flag[]๋ฅผ ๋ชจ๋‘ ๊ฐ€์ง€๊ณ  ์žˆ์Œ.

    ์ƒ๋Œ€๋ฐฉ์ด ๊นƒ๋ฐœ์„ ๋“ค๊ณ  ์žˆ๊ณ  ์ƒ๋Œ€๋ฐฉ ์ฐจ๋ก€์ด๋ฉด ๊ธฐ๋‹ค๋ฆผ

    ์ƒ๋Œ€๋ฐฉ์ด ๊นƒ๋ฐœ์„ ๋“ค๊ณ  ์žˆ์ง€๋งŒ ๋‚ด ์ฐจ๋ก€์ด๋ฉด ๋‚ด๊ฐ€ ๋“ค์–ด๊ฐ

    โ†’ Busy Waiting(spin lock) ๋ฌธ์ œ ๋‚ด ์ฐจ๋ก€๋ฅผ ํ™•์ธํ• ๋ ค๊ณ  while(1)์˜ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด์„œ ๊ณ„์† ๋‚˜์˜ ๊ฐ’์„ ์ฒดํฌํ•ด์•ผ ํ•œ๋‹ค. โ†’ CPU์™€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ„์† ๋‚ญ๋น„ํ•˜๋Š” ๊ฒƒ

์œ„์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ฝ”๋“œ๋กœ์จ Software์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ๊ฒƒ์ด๋‹ค.

Critical section ๋ฌธ์ œ๋ฅผ Hardware๋กœ ํ’€๋ฉด ๊ต‰์žฅํžˆ ์‰ฝ๊ฒŒ ํ’€ ์ˆ˜ ์žˆ๋‹ค.

Hardware์ ์œผ๋กœ Critical section์„ ํ‘ธ๋Š” ๋ฐฉ๋ฒ•

  • Test & Set
    • ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์ž‘์—…๊ณผ ์“ฐ๋Š” ์ž‘์—…์„ ๋™์‹œ์— ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋“œ์›จ์–ด๊ฐ€ ์ง€์›ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ˆ„๊ตฐ๊ฐ€ ์ฝ๊ณ  ์žˆ์„ ๋•Œ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๋Š” ์ž‘์—…์„ ํ•ด์„œ ๋ฐ์ดํ„ฐ์˜ ์†์‹ค์„ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์„ ์›์ฒœ ์ฐจ๋‹จํ•œ๋‹ค.
    • ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— ๊ฐ’์„ ์ฝ์„ ๋•Œ๋Š” ๋ฌด์กฐ๊ฑด ์ฝ๊ณ  1๋กœ ์„ธํŒ…ํ•˜๊ณ  ์ฒ˜๋ฆฌ ๋‹คํ•˜๊ณ  ๋‚˜๊ฐˆ ๋•Œ ๊ฐ’์„ 0์œผ๋กœ ๋ฐ”๊ฟ”์คŒ

์œ„์—์„œ Software, Hardware์ ์œผ๋กœ Critical Section์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์„ ๊ณต๋ถ€ํ•ด๋ณด์•˜๋Š”๋ฐ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ํ•ญ์ƒ Critical Section์„ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด์„œ ์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๊ต‰์žฅํžˆ ํž˜๋“  ์ผ์ด๋‹ค. ๋”ฐ๋ผ์„œ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋“ค์„ ์œ„ํ•ด์„œ Semaphore ๋ผ๋Š” ์ถ”์ƒ์ž๋ฃŒํ˜•์ด๋‚˜ Monitor๋ผ๋Š” ๊ฒƒ์„ ํ†ตํ•ด์„œ Critical Section์„ ๋ณด๋‹ค ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Semaphore

Semaphore โ†’ ์ถ”์ƒ์ž๋ฃŒํ˜• = ์˜ค๋ธŒ์ ํŠธ + ์˜คํผ๋ ˆ์ด์…˜

ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ถ”์ƒ์ ์œผ๋กœ Semaphore์„ ํ†ตํ•ด์„œ ๋‹จ์ˆœํžˆ ์ฝ”๋”ฉ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

Semaphore :

  • Object : Integer variable (์ž์›์˜ ๊ฐœ์ˆ˜) โ†’ ํ• ๋‹น ํ•  ์ˆ˜ ์žˆ๋Š” ์ž์›์˜ ๊ฐœ์ˆ˜
    • ๋งŒ์•ฝ Object์˜ Integer variable์ด 3์ด๋ฉด ํ•œd๋ฒˆ์— 3๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผ ๊ฐ€๋Šฅ
    • Object๊ฐ€ 0 ๋˜๋Š” 1๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ : Binary Semaphore (=mutex) type
    • Object๊ฐ€ 0 ์ด์ƒ์˜ ์ž„์˜์˜ ์ •์ˆ˜ ๊ฐ’ : Counting Semaphore type
  • operation : P ์—ฐ์‚ฐ๊ณผ V์—ฐ์‚ฐ (atomic ์—ฐ์‚ฐ 2๊ฐœ)์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Œ
    • P ์—ฐ์‚ฐ : ๋ฐ์ดํ„ฐ lock (์ž์› ํš๋“ ํ›„ lock์ด๋ฏ€๋กœ ์ž์›์„ ํš๋“ํ•˜๋Š” ๊ณผ์ •)
    • V ์—ฐ์‚ฐ : ๋ฐ์ดํ„ฐ unlock (์ž์› ๋ฐ˜๋‚ฉ ๊ณผ์ • + ํ˜น์‹œ ๋Œ€๊ธฐ์ž ์žˆ๋‹ค๋ฉด ๊นจ์›Œ์คŒ)

Semaphores๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ์— ์žˆ์–ด์„œ 2๊ฐ€์ง€ ๋ฐฉ์‹์ด ์žˆ์Œ

  1. busy-waiting(=spin lock) ๋ฐฉ์‹ โ†’ CPU๋ฅผ ์žก๊ณ  while๋ฌธ์„ ๊ณ„์† ๋Œ๋ฉด์„œ ๊ธฐ๋‹ค๋ฆผ
  2. Block/Wake up(=sleep lock) ๋ฐฉ์‹ โ†’ ๋ฆฌ์ŠคํŠธ์— ์žฌ์šด ์ƒํƒœ(CPU๋ฅผ ๋ฐ˜๋‚ฉ)๋กœ ๋‹ด๊ณ  ์ˆœ์„œ์˜ค๋ฉด ๊นจ์›Œ์คŒ

2๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ค‘ ๋ฌด์—‡์ด ๋” ์ข‹์„๊นŒ?

๋‹น์—ฐํžˆ Block/Wake up ๋ฐฉ์‹์ด ํ›จ์”ฌ ํšจ์œจ์  (blocked๋กœ ๋งŒ๋“ค์–ด์„œ CPU๋ฅผ ๊ณ„์† ๋“ค๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ)

ํ•˜์ง€๋งŒ ํ”„๋กœ์„ธ์Šค์˜ ๊ธธ์ด๊ฐ€ ๋„ˆ๋ฌด ์งง์€ ๊ฒฝ์šฐ์—๋Š” blocked, wake ํ•˜๋Š” context switch ๋•Œ๋ฌธ์— ๋น„ํšจ์œจ์ ์ผ ๋•Œ๋„ ์žˆ์ง€๋งŒ ๋ณดํ†ต์€ ํ•ญ์ƒ ํ›จ์”ฌ ํšจ์œจ์ ์ž„

Semaphore์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ 

  1. Deadlock ํ˜„์ƒ
  • ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ A๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•ด์„œ B๋ฐ์ดํ„ฐ์— ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋‘ ๋ถ€๋ถ„ ๋ชจ๋‘ ๋‹ค cpu๋ฅผ ํš๋“ํ•ด์„œ ์ผ์„ ํ•ด์•ผ ํ•˜๋Š”๋ฐ process1์ด A์— ์ ‘๊ทผํ•˜๊ณ  B์—์„œ ๋Œ€๊ธฐ์ค‘์ด๊ณ  process2๊ฐ€ B์— ์ ‘๊ทผํ•˜๊ณ  A์— ์ ‘๊ทผํ•˜๊ณ  ์žˆ์œผ๋ฉด ํ‰์ƒ ๋ฌดํ•œ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ง.

    โ†’ ์ž์›์  ํš๋“ํ•˜๋Š” ์ˆœ์„œ๋ฅผ ๋งž์ถฐ์ฃผ๋ฉด Deadlock ํ˜„์ƒ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ

    โ†’ A๋ฐ์ดํ„ฐ์— ๋ฌด์กฐ๊ฑด ๋จผ์ € ์ ‘๊ทผํ•œ ์ดํ›„์— B๋ฅผ ์ ‘๊ทผํ•˜๋„๋ก

  1. Starvation ํ˜„์ƒ (Deadlock๋„ Starvation์˜ ์ผ์ข…)
  • ํŠน์ • ํ”„๋กœ์„ธ์Šค๋“ค๋งŒ ์ž์›์„ ๊ณต์œ ํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊นจ์šฐ์ง€ ์•Š๊ณ  ์ž๊ธฐ๋“ค๋ผ๋ฆฌ๋งŒ ๋“ค์–ด๊ฐ”๋‹ค๊ฐ€ ๊นจ์šฐ๊ณ  ๋ฐ˜๋ณตํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋งํ•จ.

Semaphore ์ž์ฒด์˜ ๋ฌธ์ œ์ 

  • ์ฝ”๋”ฉ์ด ์–ด๋ ค์›€
  • ์ž‘์„ฑํ•œ ์ฝ”๋“œ์˜ ์ •ํ™•์„ฑ ์ž…์ฆ์„ ํ•˜๊ธฐ๊ฐ€ ํž˜๋“ฌ
  • ํ•œ๋ฒˆ์˜ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์‹ค์ˆ˜๊ฐ€ ์‹œ์Šคํ…œ์— ์น˜๋ช…์ ์ž„

โ†’ Monitor๋ฅผ ํ†ตํ•ด์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ

Monitor

๊ณต์œ ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Monitor์˜ ๋‚ด๋ถ€์˜ ํ”„๋กœ์‹œ์ €๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ณต์œ ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ

๋ชจ๋‹ˆํ„ฐ๊ฐ€ ์›์ฒœ์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ ๋‚ด๋ถ€์— ์žˆ๋Š” ํ”„๋กœ์‹œ์ €๋Š” ๋™์‹œ์— ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก ํ•จ

โ†’ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง์ ‘ ๋ฝ์„ ๊ฑธ ํ•„์š”๊ฐ€ ์—†์–ด์ง

โ†’ ๊ต‰์žฅํ•œ ์žฅ์ !! โ†’ ๋ณดํ†ต ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋ฝ์„ ๊ฑธ๊ณ  ํ‘ธ๋Š” ๊ณผ์ •์—์„œ ์‹ค์ˆ˜๊ฐ€ ๋งŽ์€๋ฐ ์ด๋Ÿฐ ์‹ค์ˆ˜๋ฅผ ์—†์•จ ์ˆ˜ ์žˆ์Œ

์ž์›์˜ ๊ฐœ์ˆ˜๋Š” Monitor๋„ ์•Œ์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—

variable์„ ํ†ตํ•ด์„œ ์ž์›์˜ ๊ฐœ์ˆ˜๋ฅผ ์ €์žฅํ•ด๋†“์Œ.

condition variable์€ ํ˜„์žฌ signal(), wait()์— ์“ฐ์ผ ์ƒํƒœ๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

buffer[N] โ†’ ์ž์›์˜ ๊ฐœ์ˆ˜

condition full, empty; โ†’ ์ปจ๋””์…˜์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ณ€์ˆ˜, ๊ฐ’์„ ๊ฐ€์ง€์ง€ ์•Š๊ณ  signal(), wait()์— ์“ฐ์ผ ์ƒํƒœ๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Œ.