๋ฐ์ดํ„ฐ์˜ ์ ‘๊ทผ

Race Condition

  • ํ•˜๋‚˜์˜ ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฟ์ด ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ

OS์—์„œ race condition์€ ์–ธ์ œ ๋ฐœ์ƒํ•˜๋Š”๊ฐ€?

1. kernel ์ˆ˜ํ–‰ ์ค‘ ์ธํ„ฐ๋ŸฝํŠธ ๋ฐœ์ƒ ์‹œ

Solution

  • ํ•ด๊ฒฐ์ฑ… ์ปค๋„์˜ ๊ณต์œ  ๋ณ€์ˆ˜ Count ๋ณ€์ˆ˜๋ฅผ ๊ฑด๋“œ๋ฆฌ๊ธฐ ์ „์— ์ธํ„ฐ๋ŸฝํŠธ ๋””์Šค์—์ด๋ธ”ํ•˜๊ณ  ๋๋‚˜๋ฉด ๋‹ค์‹œ ์ธ์—์ด๋ธ”ํ•˜๋Š” ๋ฐฉ์‹

2. Process๊ฐ€ system call์„ ํ•˜์—ฌ kernel mode๋กœ ์ˆ˜ํ–‰ ์ค‘์ธ๋ฐ context switch๊ฐ€ ์ผ์–ด๋‚˜๋Š” ๊ฒฝ์šฐ

  • PA๊ฐ€ CPU๋ฅผ ์žก๊ณ  user mode์—์„œ ์‹คํ–‰์ด ๋˜๋‹ค๊ฐ€ ์‹œ์Šคํ…œ ์ฝœ์„ ํ•ด์„œ kernel mode๋กœ ๋“ค์–ด์™€์„œ kernel์˜ ๋ฐ์ดํ„ฐ์ธ counter ๋ณ€์ˆ˜ ๊ฐ’์ผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์™€์ค‘์— context switch๊ฐ€ ๋ฐœ์ƒ

3. Multiprocessor์—์„œ shared memory ๋‚ด์˜ kernel data

  • ๋ฐฉ๋ฒ• 1์€ ๋งŽ์€ ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒํ•˜๊ฒŒ ๋จ -> ๋ฐฉ๋ฒ• 2๊ฐ€ ์ข‹์€ ๋ฐฉ๋ฒ•์ž„

Process Synchronization ๋ฌธ์ œ

  • ๊ณต์œ  ๋ฐ์ดํ„ฐ(shared data)์˜ ๋™์‹œ ์ ‘๊ทผ(concurrent access)์€ ๋ฐ์ดํ„ฐ์˜ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ(inconsistency)๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ
  • ์ผ๊ด€์„ฑ(consistency) ์œ ์ง€๋ฅผ ์œ„ํ•ด์„œ๋Š” ํ˜‘๋ ฅ ํ”„๋กœ์„ธ์Šค(cooperating process) ๊ฐ„์˜ ์‹คํ–‰ ์ˆœ์„œ(orderly execution)๋ฅผ ์ •ํ•ด์ฃผ๋Š” ๋งค์ปค๋‹ˆ์ฆ˜ ํ•„์š”
  • Race condition
    • ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๋“ค์ด ๋™์‹œ์— ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•˜๋Š” ์ƒํ™ฉ
    • ๋ฐ์ดํ„ฐ์˜ ์ตœ์ข… ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋Š” ๋งˆ์ง€๋ง‰์— ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฌ ํ”„๋กœ์„ธ์Šค์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง
  • race condition์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ๋Š” concurrent process๋Š” ๋™๊ธฐํ™”(synchronize)๋˜์–ด์•ผ ํ•จ

The Critical-Section Problem

  • critical section : n๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ
  • ๊ฐ ํ”„๋กœ์„ธ์Šค์˜ code segment์—๋Š” ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•˜๋Š” ์ฝ”๋“œ์ธ critical section์ด ์กด์žฌ

Problem

  • ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ critical section์— ์žˆ์„ ๋•Œ ๋‹ค๋ฅธ ๋ชจ๋“  ํ”„๋กœ์„ธ์Šค๋Š” critical section์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์—†์–ด์•ผ ํ•จ

Initial Attempts to Solve Problem

  • ๋‘ ๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ • P0, P1
  • ํ”„๋กœ์„ธ์Šค๋“ค์˜ ์ผ๋ฐ˜์ ์ธ ๊ตฌ์กฐ
do{
  entry section
  critical section
  exit section
  remainder section
} while(1);
  • critical section์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์— entry section์—์„œ lock ๊ฑธ๊ณ , exit section์—์„œ lock์„ ํ•ด์ œ
  • ํ”„๋กœ์„ธ์Šค๋“ค์€ ์ˆ˜ํ–‰์˜ ๋™๊ธฐํ™”(synchronize)๋ฅผ ์œ„ํ•ด ๋ช‡๋ช‡ ๋ณ€์ˆ˜๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Œ
    -> synchroniztion variable

ํ”„๋กœ๊ทธ๋žจ์  ํ•ด๊ฒฐ๋ฒ•์˜ ์ถฉ์กฑ ์กฐ๊ฑด

์•„๋ž˜ Algorithm๋“ค์ด ๋งŒ์กฑํ•ด์•ผํ•  ์กฐ๊ฑด๋“ค

  • Multual Exclusion (์ƒํ˜ธ ๋ฐฐ์ œ)
    • ํ”„๋กœ์„ธ์Šค Pi๊ฐ€ critical section ๋ถ€๋ถ„์„ ์ˆ˜ํ–‰ ์ค‘์ด๋ฉด ๋‹ค๋ฅธ ๋ชจ๋“  ํ”„๋กœ์„ธ์Šค๋“ค์€ ๊ทธ๋“ค์˜ critical section์— ๋“ค์–ด๊ฐ€๋ฉด ์•ˆ๋จ
  • Progress (์ง„ํ–‰)
    • ์•„๋ฌด๋„ critical section์— ์žˆ์ง€ ์•Š์€ ์ƒํƒœ์—์„œ critical section์— ๋“ค์–ด๊ฐ€๊ณ ์ž ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ์œผ๋ฉด critical section์— ๋“ค์–ด๊ฐ€๊ฒŒ ํ•ด์ฃผ์–ด์•ผ ํ•จ
  • Bounded Waiting (์œ ํ•œ๋Œ€๊ธฐ)
    • ํ”„๋กœ์„ธ์Šค๊ฐ€ critical section์— ๋“ค์–ด๊ฐ€๋ ค๊ณ  ์š”์ฒญํ•œ ํ›„๋ถ€ํ„ฐ ๊ทธ ์š”์ฒญ์ด ํ—ˆ์šฉ๋  ๋•Œ๊นŒ์ง€ ํ”„๋กœ์„ธ์Šค๋“ค์ด critical section์— ๋“ค์–ด๊ฐ€๋Š” ํšŸ์ˆ˜์— ํ•œ๊ณ„๊ฐ€ ์žˆ์–ด์•ผํ•จ

Algorithm 1

do {
  while(turn != 0); /* My turn? */
  critical section
  turn = 1;         /* Now it's your turn */
  remainder section
} while(1);
  • critical section์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— ๋‚ด ์ฐจ๋ก€์ธ์ง€๋ฅผ ์ฒดํฌํ•˜๋‹ค๊ฐ€ ์ฐจ๋ก€๊ฐ€์˜ค๋ฉด critical section์— ๋“ค์–ด๊ฐ€์„œ ๊ณต์œ  ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋๋‚˜๋ฉด ์ฐจ๋ก€๋ฅผ ์ƒ๋Œ€๋ฐฉ ์ฐจ๋ก€๋กœ ๋ฐ”๊ฟ”์คŒ
  • turn์„ ๋‘ฌ์„œ ๋™์‹œ์— critical section์— ๋“ค์–ด๊ฐ€๋Š” ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐํ•˜์˜€์ง€๋งŒ ๋ฐ˜๋“œ์‹œ ์ˆœ์„œ๋ฅผ ๊ต๋Œ€๋กœ ๋“ค์–ด๊ฐ€์•ผ(swap-turn) ํ•˜๋Š” ๋ฌธ์ œ์  ๋ฐœ์ƒ
    • turn์„ ๋‚ด ์ฐจ๋ก€๋กœ ๋ฐ”๊ฟ”์ค˜์•ผ๋งŒ critical section์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ
    • ์ƒ๋Œ€๋ฐฉ์ด critical section์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ฐจ๋ก€๊ฐ€ ๋Œ์•„์˜ค์ง€ ์•Š์Œ
  • ์›ํ•˜๋“  ์›ํ•˜์ง€ ์•ˆ๋“  ๋ฌด์กฐ๊ฑด ์ฐจ๋ก€๊ฐ€ ์˜ค๋ฉด critical section์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋จ

Multual Exclusion์€ ์ถฉ์กฑํ•˜์˜€์ง€๋งŒ Progress๋Š” ์ถฉ์กฑํ•˜์ง€ ๋ชปํ•จ

Algorithm 2

do {
  flag[i] = true;   /* Pretend I am in */
  while (flag[j]);  /* Is he also in? then wait */
  critical section
  flag[i] = false;  /* I am out now */
  remainder section
} while(1);
  • Pi๊ฐ€ flag[i]๋ฅผ ๋“ค์–ด์„œ critical section์— ๋“ค์–ด๊ฐ€๊ณ  ์‹ถ๋‹ค๋Š” ์˜์‚ฌ๋ฅผ ํ‘œํ˜„ ํ›„ Pj์˜ flag[j]์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ๋งŒ์•ฝ ๋๋‚ฌ์œผ๋ฉด flag[j] ๊นƒ๋ฐœ์„ ๋‚ด๋ฆฌ๊ฒŒ ๋˜๊ณ  flag[i]๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋จ
  • ์„œ๋กœ ๊นƒ๋ฐœ๋งŒ ๋“ค๊ณ  ์žˆ๋‹ค๊ฐ€ CPU๋ฅผ ๋บ๊ฒจ ์„œ๋กœ ์–‘๋ณดํ•˜๋Š” ์ƒํ™ฉ ๋ฐœ์ƒ
    • Progress ๋ฌธ์ œ ๋ฐœ์ƒ

Multual Exclusion์€ ์ถฉ์กฑํ•˜์˜€์ง€๋งŒ Progress๋Š” ์ถฉ์กฑํ•˜์ง€ ๋ชปํ•จ

Algorithm 3 (Petersonโ€™s Algorithm)

do {
  flag[i] = true;   /* My intention is to enter ... */
  turn = j;         /* Set to his turn */
  while (flag[i] && turn == j);  /* wait only if ... */
  critical section
  flag[i] = false;
  remainder section
} while(1);
  • ๊นƒ๋ฐœ์„ ํ†ตํ•ด์„œ ๋“ค์–ด๊ฐ€๊ฒ ๋‹ค๋Š” ์˜์‚ฌ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ  ์ƒ๋Œ€๋ฐฉ์ด ๊นƒ๋ฐœ์„ ๋“ค๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธ
  • ๋™์‹œ์— ๊นƒ๋ฐœ์„ ๋“  ์ƒํ™ฉ์—์„œ๋Š” turn์„ ์ด์šฉํ•ด์„œ ์ •ํ•ด์คŒ
  • Bysy Waiting (= spin lock)
    • CPU์™€ memory๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ -> ๋น„ํšจ์œจ์ 

Synchroniztion Hardware

Semaphores

P ์—ฐ์‚ฐ : ์ž์›์„ ํš๋“ํ•˜๋Š” ๊ณผ์ • = lock ๊ณผ์ • V ์—ฐ์‚ฐ : ์ž์›์„ ๋ฐ˜๋‚ฉํ•˜๋Š” ๊ณผ์ • = unlock ๊ณผ์ •

Two Types of Semaphores

  • Counting semaphore
    • ๋„๋ฉ”์ธ์ด 0 ์ด์ƒ์ธ ์ž„์˜์˜ ์ •์ˆ˜๊ฐ’
    • ์ฃผ๋กœ resource counting์— ์‚ฌ์šฉ
  • Binary semaphore (= mutex)
    • 0 or 1 ๊ฐ’๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” semaphore
    • ์ฃผ๋กœ mutual exclusion (lock/unlock)์— ์‚ฌ์šฉ

Semaphores

  • ์ผ์ข…์— ์ถ”์ƒ ์ž๋ฃŒํ˜•

P(S) : ๊ณต์œ ๋ฐ์ดํ„ฐ๋ฅผ ํš๋“ํ•˜๋Š” ๊ณผ์ •

V(S) : ๊ณต์œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋‚ฉํ•˜๋Š” ๊ณผ์ •

Deadlock and Starvation

Deadlock

  • ๋‘˜ ์ด์ƒ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์„œ๋กœ ์ƒ๋Œ€๋ฐฉ์— ์˜ํ•ด ์ถฉ์กฑ๋  ์ˆ˜ ์žˆ๋Š” event๋ฅผ ๋ฌดํ•œํžˆ ๊ธฐ๋‹ค๋ฆฌ๋Š” ํ˜„์ƒ
    • P0์ž…์žฅ์—์„œ๋Š” Q๋ฅผ ๋ชป์–ป๊ณ  P1์ž…์žฅ์—์„œ๋Š” S๋ฅผ ๊ณ„์† ๋ชป ์–ป๋Š” ์ƒํ™ฉ
    • ํ”„๋กœ์„ธ์Šค๋“ค์€ P์—ฐ์‚ฐ์œผ๋กœ ์ž์›์„ ํ•œ๋ฒˆ์— ์–ป๊ณ  V์—ฐ์‚ฐ์œผ๋กœ ํ•œ๋ฒˆ์— ๋ฐ˜๋‚ฉ์„ ํ•จ
    • P0์™€ P1์€ S์™€ Q๋ฅผ ๋™์‹œ์— ์–ป์–ด์„œ ๋™์‹œ์— ๋ฐ˜๋‚ฉ
  • S์™€ Q๊ฐ€ 1๋กœ ์ดˆ๊ธฐํ™”๋œ semaphore

Starvation

  • indefinite blocking ํ”„๋กœ์„ธ์Šค๊ฐ€ suspend๋œ ์ด์œ ์— ํ•ด๋‹นํ•˜๋Š” ์„ธ๋งˆํฌ์–ด ํ์—์„œ ๋น ์ ธ๋‚˜๊ฐˆ ์ˆ˜ ์—†๋Š” ํ˜„์ƒ

Classical Problem of Synchronization

  • Bounded-Buffer Problem (Producer-Consumer Problem)
  • Readers and Writers Problem
  • Dining-Philosophers Problem

Bounded-Buffer Problem (Producer-Consumer Problem)

Producer Process์—๊ฒŒ๋Š” Empty ๋ฒ„ํผ๊ฐ€ ์ž์›, Consumer Process์—๊ฒŒ๋Š” Full ๋ฒ„ํผ๊ฐ€ ์ž์›์ด๋‹ค.

Shared data(๊ณต์œ  ๋ฐ์ดํ„ฐ)

  • buffer ์ž์ฒด ๋ฐ buffer ์กฐ์ž‘ ๋ณ€์ˆ˜(empty/full buffer์˜ ์‹œ์ž‘ ์œ„์น˜)
    • ๊ณต์œ  ๋ฐ์ดํ„ฐ์—๋Š” lock์„ ๊ฑธ์–ด์„œ ๋™์‹œ ์ ‘๊ทผ์„ ๋ง‰์•„์•ผํ•จ

Synchroniztion variables

  • mutual exclusion -> Need binary semaphore(shared data์˜ mutual exclusion์„ ์œ„ํ•ด)
    • binary semaphore๋ฅผ ํ†ตํ•ด ์ž์›์„ lock/unlock ํ•จ
  • resource count -> Need integer semaphore(๋‚จ์€ full/empty buffer์˜ ์ˆ˜ ํ‘œ์‹œ)
    • counting semaphore๋ฅผ ํ†ตํ•ด ์ž์›์˜ ์ˆ˜๋ฅผ ์…ˆ

Code

  • semaphore full = 0, empty = n, mutex(lock/unlock์„ ์œ„ํ•œ ๋ณ€์ˆ˜) = 1

Readers-Writers Problem

  • ํ•œ process๊ฐ€ db์— write์ค‘์ผ ๋•Œ ๋‹ค๋ฅธ process๊ฐ€ ์ ‘๊ทผํ•˜๋ฉด ์•ˆ ๋จ
  • read๋Š” ๋™์‹œ์— ์—ฌ๋Ÿฟ์ด ์ ‘๊ทผํ•ด๋„ ๋จ

Solution

  • writer๊ฐ€ db์— ์ ‘๊ทผ ํ—ˆ๊ฐ€๋ฅผ ์•„์ง ์–ป์ง€ ๋ชปํ•œ ์ƒํƒœ์—์„œ๋Š” ๋ชจ๋“  ๋Œ€๊ธฐ์ค‘์ธ reader๋“ค์„ ๋‹ค db์— ์ ‘๊ทผํ•˜๊ฒŒ ํ•ด์คŒ
  • writer๋Š” ๋Œ€๊ธฐ ์ค‘์ธ reader๊ฐ€ ํ•˜๋‚˜๋„ ์—†์„ ๋•Œ db ์ ‘๊ทผ์ด ํ—ˆ์šฉ๋œ๋‹ค
  • ์ผ๋‹จ writer๊ฐ€ db์— ์ ‘๊ทผ์ค‘์ด๋ฉด reader๋“ค์€ ์ ‘๊ทผ์ด ๊ธˆ์ง€๋œ๋‹ค.
  • writer๊ฐ€ db์—์„œ ๋น ์ ธ๋‚˜๊ฐ€์•ผ๋งŒ reader์˜ ์ ‘๊ทผ์ด ํ—ˆ์šฉ๋œ๋‹ค.

Shared data

  • DB ์ž์ฒด
  • readcoun : ํ˜„์žฌ DB์— ์ ‘๊ทผ ์ค‘์ธ Reader์˜ ์ˆ˜

Synchroniztion variables

  • mutex : readcount๋ฅผ ์ ‘๊ทผํ•˜๋Š” ์ฝ”๋“œ(critical section)์˜ mutual exclusion ๋ณด์žฅ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.
  • db : reader์™€ writer๊ฐ€ ๊ณต์œ  db ์ž์ฒด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ ‘๊ทผํ•˜๊ฒŒ ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

Code

  • Shared data
    • int readcount = 0;
    • DB ์ž์ฒด;
  • Synchronization variables
    • semaphore mutex = 1, db= 1;
  • writer๊ฐ€ ๋จผ์ € ๋„์ฐฉํ–ˆ์„ ์ง€๋ผ๋„ reader๊ฐ€ ๊ณ„์† ๋“ค์–ด์˜จ๋‹ค๋ฉด starvation ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

Dining-Philosophers Problem

์•ž์˜ solution์˜ ๋ฌธ์ œ์ 

  • Deadlock ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Œ
  • ๋ชจ๋“  ์ฒ ํ•™์ž๊ฐ€ ๋™์‹œ์— ๋ฐฐ๊ฐ€ ๊ณ ํŒŒ์ ธ ์™ผ์ชฝ ์ “๊ฐ€๋ฝ์„ ์ง‘์–ด๋ฒ„๋ฆฐ ๊ฒฝ์šฐ

ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

  • 4๋ช…์˜ ์ฒ ํ•™์ž๋งŒ์ด ํ…Œ์ด๋ธ”์— ๋™์‹œ์— ์•‰์„ ์ˆ˜ ์žˆ๋„๋ก ํ•จ
  • ์ “๊ฐ€๋ฝ์„ ๋‘ ๊ฐœ ๋ชจ๋‘ ์ง‘์„ ์ˆ˜ ์žˆ์„ ๋•Œ์—๋งŒ ์ “๊ฐ€๋ฝ์„ ์ง‘์„ ์ˆ˜ ์ž‡๊ฒŒ ํ•จ
  • ๋น„๋Œ€์นญ
    • ์ง์ˆ˜(ํ™€์ˆ˜) ์ฒ ํ•™์ž๋Š” ์™ผ์ชฝ(์˜ค๋ฅธ์ชฝ) ์ “๊ฐ€๋ฝ๋ถ€ํ„ฐ ์ง‘๋„๋กํ•จ

Code

Monitor

Semaphore์˜ ๋ฌธ์ œ์ 

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

Monitor

  • ๋™์‹œ ์ˆ˜ํ–‰์ค‘์ธ ํ”„๋กœ์„ธ์Šค ์‚ฌ์ด์—์„œ abstract data type์˜ ์•ˆ์ „ํ•œ ๊ณต์œ ๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•œ high-level synchronization construct

reference

์šด์˜์ฒด์ œ - ์ดํ™”์—ฌ์ž๋Œ€ํ•™๊ต