Search
Duplicate

병행 μ œμ–΄

λ°μ΄ν„°μ˜ μ ‘κ·Ό

β†’ μ €μž₯κ³Ό μ—°μ‚°ν•˜λŠ” 곳이 닀름

Race Condition

β€’
μ—¬λŸ¬ 주체가 ν•˜λ‚˜μ˜ 데이터에 λ™μ‹œμ— μ ‘κ·Όν•˜λ €κ³  ν•  λ•Œ
storage box λŠ” λ©”λͺ¨λ¦¬ μ£Όμ†Œ 곡간, λ©”λͺ¨λ¦¬, λ””μŠ€ν¬
execution box λŠ” CPU ν”„λ‘œμ„ΈμŠ€, CPU, 컴퓨터 λ‚΄λΆ€
β†’ λ©€ν‹°ν”„λ‘œμ„Έμ„œ or 곡유 λ©”λͺ¨λ¦¬ μ‚¬μš© λ“±μœΌλ‘œ 인해 race condition λ°œμƒ

OS μ—μ„œ race condition 이 λ°œμƒν•˜λŠ” 경우

1.
kernel μˆ˜ν–‰ 쀑 interrupt λ°œμƒ μ‹œ
β€’
interrupt handler vs kernel
β€’
load ν•˜κ³  increase ν•˜κ³  store ν•˜λŠ” μ„Έ 개의 μΈμŠ€νŠΈλŸ­μ…˜μ΄ μˆ˜ν–‰λ˜λŠ” λ™μ•ˆ λ°œμƒ
β€’
컀널 λͺ¨λ“œ running 쀑 interrupt κ°€ λ°œμƒν•˜μ—¬ interrupt 처리 루틴 μˆ˜ν–‰ β†’ μ–‘μͺ½ λ‹€ 컀널 μ½”λ“œμ΄λ―€λ‘œ kernel address space 곡유
β€’
ν•΄κ²° λ°©λ²•μœΌλ‘œλŠ” interrupt λ₯Ό disable μ‹œν‚€κ³  λ‚˜μ„œ interrupt μ‹€ν–‰
2.
process κ°€ system call 을 ν•˜μ—¬ kernel mode 둜 μˆ˜ν–‰ 쀑에 context switch κ°€ μΌμ–΄λ‚˜λŠ” 경우
β€’
ν•΄κ²° λ°©λ²•μœΌλ‘œλŠ” 컀널 λͺ¨λ“œμ—μ„œ μˆ˜ν–‰ 쀑일 λ•ŒλŠ” ν• λ‹Ή μ‹œκ°„μ΄ μ§€λ‚˜λ„ CPU λ₯Ό preempt ν•˜μ§€ μ•Šκ³  컀널 λͺ¨λ“œμ—μ„œ μ‚¬μš©μž λͺ¨λ“œλ‘œ λŒμ•„κ°ˆ λ•Œ preempt ν•œλ‹€.
3.
multiprocessor μ—μ„œ shared memory λ‚΄μ˜ kernel data
β€’
ν•΄κ²° λ°©λ²•μœΌλ‘œλŠ” 컀널 λ‚΄λΆ€ 각 곡유 데이터에 μ ‘κ·Όν•  λ•Œλ§ˆλ‹€ κ·Έ 데이터에 λŒ€ν•œ lock, unlock 을 ν•œλ‹€.

Process Synchronization 문제

β€’
곡유 데이터(shared data) 에 λŒ€ν•œ λ™μ‹œ μ ‘κ·Ό(concurrent access) 은 λ°μ΄ν„°μ˜ 뢈일치 문제λ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆλ‹€.
β€’
일관성(consistency) μœ μ§€λ₯Ό μœ„ν•΄ ν˜‘λ ₯ ν”„λ‘œμ„ΈμŠ€ κ°„μ˜ μ‹€ν–‰ μˆœμ„œλ₯Ό μ •ν•΄μ£ΌλŠ” λ©”μ»€λ‹ˆμ¦˜μ΄ ν•„μš”

Race Condition

β€’
μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ λ™μ‹œμ— 곡유 데이터에 μ ‘κ·Όν•˜λŠ” 상황
β€’
λ°μ΄ν„°μ˜ μ΅œμ’… μ—°μ‚° κ²°κ³ΌλŠ” λ§ˆμ§€λ§‰μ— κ·Έ 데이터λ₯Ό 닀룬 ν”„λ‘œμ„ΈμŠ€μ— 따라 달라진닀.
β€’
race condition 을 막기 μœ„ν•΄ concurrent process λŠ” 동기화(synchronize) λ˜μ–΄μ•Ό ν•œλ‹€.
μ‚¬μš©μž ν”„λ‘œμ„ΈμŠ€ P1 μˆ˜ν–‰ 쀑 timer interrupt κ°€ λ°œμƒν•΄μ„œ context switch κ°€ μΌμ–΄λ‚˜ P2 κ°€ CPU λ₯Ό μž‘λŠ”λ‹€λ©΄?

The Critical-Section Problem(μž„κ³„κ΅¬μ—­)

β€’
μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€κ°€ 곡유 데이터λ₯Ό λ™μ‹œμ— μ‚¬μš©ν•˜κΈ°λ₯Ό μ›ν•˜λŠ” 경우
β€’
각 ν”„λ‘œμ„ΈμŠ€μ˜ code segment μ—λŠ” 곡유 데이터에 μ ‘κ·Όν•˜λŠ” μ½”λ“œμΈ critical section 이 쑴재
β€’
count++ 등이 critical section 의 μ˜ˆμ‹œ
β€’
ν•΄κ²°μ±…
{ entry section; critical section; exit section; }
C
볡사
μž„κ³„ ꡬ역에 λ“€μ–΄κ°€κΈ° 전에 lock λ“±μœΌλ‘œ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ˜ 접근을 λ§‰λŠ”λ‹€.

해결법 쑰건

β€’
Mutual Exclusion(μƒν˜Έ 배제)
β—¦
ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€κ°€ critical section 뢀뢄을 μˆ˜ν–‰ 쀑이면 λ‹€λ₯Έ λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€λ“€μ€ critical section 에 λ“€μ–΄κ°€λ©΄ μ•ˆλœλ‹€.
β€’
Progress
β—¦
아무도 critical section 에 μžˆμ§€ μ•Šμ€ μƒνƒœμ—μ„œ critical section 에 λ“€μ–΄κ°€κ³ μž ν•˜λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ 있으면 critical section 에 λ“€μ–΄κ°ˆ 수 μžˆλ‹€.
β€’
Bounded Waiting(μœ ν•œ λŒ€κΈ°)
β—¦
ν”„λ‘œμ„ΈμŠ€κ°€ critical section 에 λ“€μ–΄κ°€λ €κ³  μš”μ²­ν•œ ν›„λΆ€ν„° κ·Έ μš”μ²­μ΄ ν—ˆμš©λ  λ•ŒκΉŒμ§€ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€λ“€μ΄ critical section 에 λ“€μ–΄κ°€λŠ” νšŸμˆ˜μ— ν•œκ³„κ°€ μžˆμ–΄μ•Ό ν•œλ‹€.
β—¦
μž„κ³„ ꡬ역에 λ“€μ–΄κ°€κ³ μž ν•˜λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ 3개 있고 μž„κ³„ ꡬ역에 2개의 ν”„λ‘œμ„ΈμŠ€λ§Œ λ²ˆκ°ˆμ•„κ°€λ©΄μ„œ λ“€μ–΄κ°€λŠ” 경우 ν•΄λ‹Ή 쑰건을 μΆ©μ‘±ν•˜μ§€ λͺ»ν•¨

Algorithm 1

do { while (turn != 0); critical section turn = 1; } while (1);
C
볡사
β€’
do while κ³Ό turn 으둜 ꡬ뢄
β€’
progress 쑰건을 λ§Œμ‘±ν•˜μ§€ λͺ»ν•œλ‹€.
β—¦
ν”„λ‘œμ„ΈμŠ€ 0이 1μ΄ˆμ— 10번 critical section 에 λ“€μ–΄κ°€κ³  ν”„λ‘œμ„ΈμŠ€ 1이 1μ΄ˆμ— 1번 critical section 에 λ“€μ–΄κ°€λ©΄ ν”„λ‘œμ„ΈμŠ€ 0은 1μ΄ˆμ— 1λ²ˆλ°–μ— critical section에 듀어가지 λͺ»ν•œλ‹€. ν”„λ‘œμ„ΈμŠ€ 1이 λ“€μ–΄κ°€μ„œ 0으둜 λ°”κΏ”μ€˜μ•Ό ν•˜κΈ°λ•Œλ¬Έμ—

Algorithm 2

do { flag[i] = true; while (flag[j]); critical section flag[i] = false; } while (1);
C
볡사
β€’
flag[j] κ°€ true κ°€ 아닐 λ•Œ ν”„λ‘œμ„ΈμŠ€ i κ°€ criticaal section 에 λ“€μ–΄κ°ˆ 수 μžˆλ‹€.
β€’
progress 쑰건을 λ§Œμ‘±ν•˜μ§€ λͺ»ν•œλ‹€.
β—¦
i 와 j λ™μ‹œμ— flagλ₯Ό true 둜 λ§Œλ“€λ©΄ 두 ν”„λ‘œμ„ΈμŠ€ λͺ¨λ‘ while μ—μ„œ λŒ€κΈ°

Algorithm 3 (Peterson’s Algorithm)

do { flag[i] = true; turn = j; while (flag[j] && turn ==j); critical section flag[i] = false; } while (1);
C
볡사
β€’
Algorithm 1, 2 λ₯Ό κ²°ν•©ν•œ 것
β€’
쑰건을 λͺ¨λ‘ λ§Œμ‘±ν•¨
β€’
busy waiting(spin lock) 문제
β—¦
계속 CPU 와 memory λ₯Ό μ“°λ©΄μ„œ wait

Synchronization Hardware

β€’
ν•˜λ“œμ›¨μ–΄λ‘œ test & modify λ₯Ό atomic ν•˜κ²Œ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ μ§€μ›ν•˜λŠ” 경우 λ¬Έμ œκ°€ μ‰½κ²Œ ν•΄κ²° κ°€λŠ₯
β—¦
곡유 λ°μ΄ν„°μ˜ μ½λŠ” μž‘μ—…κ³Ό μ“°λŠ” μž‘μ—…μ„ ν•œλ²ˆμ— μˆ˜ν–‰ν•˜λ©΄ ν•΄κ²° κ°€λŠ₯
β—¦
test_and_set(a) λΌλŠ” μΈμŠ€νŠΈλŸ­μ…˜

Semaphores

β€’
Semaphore S:
β—¦
integer(μžμ›μ˜ 갯수)
β—¦
P, V 연산에 μ˜ν•΄μ„œλ§Œ μ ‘κ·Ό κ°€λŠ₯
β—¦
atomic μ—°μ‚°
β€’
P(S):
β—¦
while (S≀0) wait;
β—¦
Sβ€”;
β—¦
μ„Έλ§ˆν¬μ–΄ λ³€μˆ˜ 값을 νšλ“ν•˜λŠ” μ—°μ‚°
β—¦
S 값이 μ–‘μˆ˜κ°€ 될 λ•ŒκΉŒμ§€ busy-wait
β€’
V(S):
β—¦
S++;
β—¦
λ°˜λ‚©ν•˜λŠ” μ—°μ‚°
do { P(mutex); /* mutext λŠ” mutual exclusion */ critical section V(mutex); } while (1);
C
볡사
β€’
busy wait 방식(spin lock)
β€’
block & wakeup 방식(sleep lock) 으둜 ν•΄κ²° κ°€λŠ₯

Block & Wakeup 방식

β€’
Semaphore λ₯Ό integer λ³€μˆ˜ κ°’(value)κ³Ό queue λ³€μˆ˜ κ°’(L)으둜 μ •μ˜
β€’
value 값이 λ‹¨μˆœνžˆ 곡유 κ°€λŠ₯ μžμ› κ°œμˆ˜κ°€ μ•„λ‹ˆλΌ, 곡유 κ°€λŠ₯ν•œμ§€ 상황을 λ‚˜νƒ€λ‚Έλ‹€. 음수면 곡유 λΆˆκ°€, μ–‘μˆ˜λ©΄ 곡유 κ°€λŠ₯
β€’
P(S):
S.value--; if (S.value < 0 ) { add this process to S.L; block(); }
C
볡사
β—¦
value κ°€ λΆ€μ‘±ν•˜λ©΄ block 됨
β€’
V(S):
S.value++; if (S.value <= 0) { remove a process P from S.L; wakeup(P); }
C
볡사
β—¦
λ‹¨μˆœνžˆ μžμ›μ„ λ°˜λ‚©ν•˜κ³  λλ‚˜λŠ”κ²Œ μ•„λ‹ˆλΌ ν˜Ήμ‹œ μž λ“€μ–΄ μžˆλŠ” ν”„λ‘œμ„ΈμŠ€κ°€ μžˆλ‹€λ©΄ 깨움

busy-wait vs block & wakeup

β€’
critical section 의 길이가 짧으면 busy-wait 방식도 μ’‹μŒ
β€’
μΌλ°˜μ μœΌλ‘œλŠ” block & wakeup

binary semaphore(mutex)

β€’
μžμ›μ˜ 값이 ν•˜λ‚˜μΈ 경우(값이 0, 1)
β€’
주둜 lock/unlock 에 μ‚¬μš©

counting semaphore

β€’
μžμ›μ˜ κ°œμˆ˜κ°€ μ—¬λŸ¬κ°œ μžˆμ„ λ•Œ
β€’
resource counting 에 μ‚¬μš©

Deadlock and Starvation

Deadlock

λ‘˜ μ΄μƒμ˜ ν”„λ‘œμ„ΈμŠ€κ°€ μ„œλ‘œ μƒλŒ€λ°©μ— μ˜ν•΄ 좩쑱될 수 μžˆλŠ” event λ₯Ό λ¬΄ν•œνžˆ κΈ°λ‹€λ¦¬λŠ” ν˜„μƒ
β€’
μ„Έλ§ˆν¬μ–΄ S, Q 두 κ°œκ°€ μžˆμ„ λ•Œ μ–΄λ–€ 일을 ν•˜κΈ° μœ„ν•΄ 두 개 λͺ¨λ‘ νšλ“ν•΄μ•Ό 일을 ν•  수 μžˆλŠ” 경우 λ°λ“œλ½ λ°œμƒ
β€’
P0 이 P(S) λ₯Ό μ–»κ³  CPU λ₯Ό P1 이 가져감.
β€’
P1 이 P(Q) λ₯Ό μ–»κ³  P(S) λ₯Ό μ–»μœΌλ €κ³  ν•  λ•Œ λ¬΄ν•œμ • λŒ€κΈ°
β€’
해결방법: S, Q λ₯Ό μ–»λŠ” μˆœμ„œλ₯Ό ν•˜λ‚˜λ‘œ μ •ν•΄μ£Όλ©΄ λœλ‹€.

Starvation

νŠΉμ •ν•œ ν”„λ‘œμ„ΈμŠ€κ°€ μ˜μ›νžˆ μžμ›μ„ 얻지 λͺ»ν•˜κ³  κΈ°λ‹€λ¦¬λŠ” ν˜„μƒ
β€’
특히 일뢀 ν”„λ‘œμ„ΈμŠ€λ§Œ μžμ›μ„ 가지고 νŠΉμ • ν”„λ‘œμ„ΈμŠ€λ§Œ λͺ»κ°€μ§€λŠ” ν˜„μƒ. λ°λ“œλ½μ€ κ΄€λ ¨λœ λͺ¨λ“  ν”„λ‘œμ„ΈμŠ€κ°€ λͺ¨λ‘ λͺ»κ°€μ§.

Classical Problems of Synchronization

Bounded-Buffer Problem(Producer-Consumer Problem)

Producer 와 Consumer κ°€ μ—¬λŸ¬ 개
1.
μƒμ‚°μžλ‚˜ μ†ŒλΉ„μž 2κ°œκ°€ ν•œλ²ˆμ— 왔을 λ•Œ
β€’
데이터λ₯Ό λ™μ‹œμ— λ„£μœΌλ €κ³  함
β€’
데이터λ₯Ό λ™μ‹œμ— κΊΌλ‚΄λ €κ³  함
β€’
곡간(buffer)에 락을 κ±Έμ–΄μ„œ 진행
2.
bufferκ°€ 가득 찼을 λ•Œ
a.
데이터λ₯Ό 집어 넣을 buffer κ°€ μ—†λ‹€
b.
κ·Έλž˜μ„œ μƒμ‚°μžλŠ” λŒ€κΈ°
β€’
동기화 λ³€μˆ˜λ‘œλŠ” 1. binary semaphore 와 2. integer semaphore
λ³€μˆ˜λŠ” full = 0, empty = n, mutex = 1; 둜 μ‹œμž‘
β€’
P(empty) μ—μ„œ empty κ°€ 0이 μ•„λ‹ˆλΌλ©΄ 버퍼 ν”„λ‘œμ„ΈμŠ€ νšλ“ ν›„ mutex λ₯Ό 0으둜 λ°”κΏˆ(락)
β€’
V(mutex) 둜 λ°˜λ‚© ν›„ V(full) 둜 full λ³€μˆ˜μ— 1을 μ¦κ°€μ‹œν‚΄

Readers and Writers Problem

β€’
DB μ—μ„œ λ°œμƒ
β€’
ν•œ ν”„λ‘œμ„ΈμŠ€κ°€ db 에 write 쀑일 λ•Œ λ‹€λ₯Έ process κ°€ μ ‘κ·Όν•˜λ©΄ μ•ˆλ¨
β€’
read λŠ” λ™μ‹œμ— μ—¬λŸΏμ΄μ„œ 해도 됨
β€’
ν•΄κ²°μ±…:
β—¦
writer κ°€ db 에 μ ‘κ·Ό ν—ˆκ°€λ₯Ό 아직 얻지 λͺ»ν•œ μƒνƒœμ—μ„œλŠ” λͺ¨λ“  λŒ€κΈ°μ€‘μΈ reader 듀을 λ‹€ db 에 μ ‘κ·Όν•˜κ²Œ ν•΄μ€€λ‹€.
β—¦
writer λŠ” λŒ€κΈ°μ€‘μΈ reader κ°€ ν•˜λ‚˜λ„ 없을 λ•Œ db 접근이 ν—ˆμš©λ¨
β—¦
일단 writer κ°€ db 에 μ ‘κ·Ό 쀑이면 reader 듀은 접근이 κΈˆμ§€λ¨
β—¦
writer κ°€ db μ—μ„œ λΉ μ Έλ‚˜κ°€μ•Όλ§Œ reader 의 접근이 ν—ˆμš©
β€’
곡유 데이터
β—¦
db 자체
β—¦
read count
β€’
mutex λŠ” readcount 에 λŒ€ν•œ 배타락을 μ–»κΈ° μœ„ν•œ μ„Έλ§ˆν¬μ–΄ λ³€μˆ˜
β€’
starvation 이 λ°œμƒν•  수 있음. μ˜ˆμ‹œ(μ‹ ν˜Έλ“± 쑴재 이유)

Dining Philosophers Problem

β€’
semaphore chopstick[5];
β€’
μ²˜μŒμ— λͺ¨λ“  values λŠ” 1
β€’
μƒκ°ν•˜λŠ” 업무와 λ°₯λ¨ΉλŠ” 업무 2개 있음
β€’
문제점:
β—¦
λ°λ“œλ½ λ°œμƒ κ°€λŠ₯μ„±
β–ͺ
λ‹€ 각각 μ™Όμͺ½ 젓가락 μž‘μ•˜μ„ λ•Œ
β€’
ν•΄κ²°μ±…
β—¦
4λͺ…μ˜ μ² ν•™μžλ§Œ ν…Œμ΄λΈ”μ— 앉을 수 μžˆλ„λ‘
β—¦
젓가락을 두 개 λͺ¨λ‘ 집을 수 μžˆμ„ λ•Œμ—λ§Œ 젓가락을 집을 수 있게
β—¦
짝수 μ² ν•™μžλŠ” μ™Όμͺ½, ν™€μˆ˜ μ² ν•™μžλŠ” 였λ₯Έμͺ½ 젓가락 λΆ€ν„° 집도둝 λΉ„λŒ€μΉ­ μ „λž΅
β—¦
β€’
self[5] λŠ” 집을 수 μžˆλŠ” κΆŒν•œ, μ΄ˆκΈ°ν™” 값은 0
β€’
이 뢀뢄이 일반적인 μ„Έλ§ˆν¬μ–΄μ˜ μ² ν•™κ³ΌλŠ” 닀름
β—¦
μžμ›μ˜ 개수λ₯Ό μ΄ˆκΈ°κ°’μœΌλ‘œ ν•˜κ³  κ·Έ μžμ›μ˜ κ°œμˆ˜κ°€ 1μ΄κ±°λ‚˜ 1이상일 λ•Œλ₯Ό κΆŒν•œμœΌλ‘œ λ΄„
β—¦
κΆŒν•œμ„ μ£ΌλŠ”κ²Œ V(self[i]) β†’ 0μ΄μ—ˆλ˜ 값을 1둜 λ°”κΏˆ

Monitor

β€’
Semaphore 의 문제점
β—¦
μ½”λ”©ν•˜κΈ° νž˜λ“¦
β—¦
μ •ν™•μ„±μ˜ μž…μ¦μ΄ 어렀움
β—¦
자발적 ν˜‘λ ₯이 ν•„μš”
β—¦
ν•œλ²ˆμ˜ μ‹€μˆ˜κ°€ λͺ¨λ“  μ‹œμŠ€ν…œμ— 치λͺ…적인 영ν–₯
β€’
μ–Έμ–΄ μ°¨μ›μ—μ„œ 동기화 문제 ν•΄κ²°
β€’
λ™μ‹œ μˆ˜ν–‰μ€‘μΈ ν”„λ‘œμ„ΈμŠ€ 사이 abstract data type 의 μ•ˆμ „ν•œ 곡유λ₯Ό 보μž₯ν•˜κΈ° μœ„ν•œ high-level 동기화 construct
monitor monitor_name { procedure body P1 (...) { ... } procedure body P2 (...) { ... } procedure body Pn (...) { ... } { initialization code } }
Java
볡사
β€’
객체지ν–₯ 언어듀은 객체λ₯Ό μ€‘μ‹¬μœΌλ‘œ operation 듀이 μ •μ˜λœλ‹€.
β€’
곡유 데이터에 μ ‘κ·Όν•˜κΈ° μœ„ν•΄μ„œλŠ” 내뢀에 procedure λ₯Ό ν†΅ν•΄μ„œλ§Œ 곡유 데이터에 μ ‘κ·Όν•  수 μžˆλ‹€.
β€’
β€’
ν”„λ‘œκ·Έλž˜λ¨Έκ°€ 데이터에 락을 κ±Έ ν•„μš”κ°€ μ—†λ‹€.
β€’
λͺ¨λ‹ˆν„°κ°€ μ›μ²œμ μœΌλ‘œ ν”„λ‘œμ‹œμ €κ°€ λ™μ‹œμ— μ‹€ν–‰ν•  수 없도둝 ν•œλ‹€.
β€’
μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€κ°€ λ™μ‹œμ— 접근해도 λͺ¨λ‹ˆν„°κ°€ μ•Œμ•„μ„œ queue 에 쀄 μ„Έμš°κ³  ν”„λ‘œμ‹œμ €λ₯Ό 순차적으둜 μ‹€ν–‰μ‹œμΌœμ€€λ‹€.
β€’
λͺ¨λ‹ˆν„° λ‚΄μ—μ„œλŠ” ν•œλ²ˆμ— ν•˜λ‚˜μ˜ ν”„λ‘œμ„ΈμŠ€λ§Œ ν™œλ™ κ°€λŠ₯
β€’
ν”„λ‘œκ·Έλž˜λ¨Έκ°€ 동기화 μ œμ•½ 쑰건(lock)을 λͺ…μ‹œμ μœΌλ‘œ μ½”λ”©ν•  ν•„μš”κ°€ μ—†λ‹€.
β€’
ν”„λ‘œμ„ΈμŠ€κ°€ λͺ¨λ‹ˆν„° μ•ˆμ—μ„œ 기닀릴 수 μžˆλ„λ‘ ν•˜κΈ° μœ„ν•΄ condition variable(x, y) 을 μ‚¬μš©
β€’
condition variable 은 wait 와 signal 연산에 μ˜ν•΄μ„œλ§Œ 접근이 κ°€λŠ₯ν•˜λ‹€.
β€’
wait()
β—¦
x.wait() 을 invoke ν•œ ν”„λ‘œμ„ΈμŠ€λŠ” λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€κ°€ x.signal() 을 invoke ν•˜κΈ° μ „κΉŒμ§€ suspend 됨
β€’
signal()
β—¦
x.signal()은 μ •ν™•ν•˜κ²Œ ν•˜λ‚˜μ˜ suspend 된 ν”„λ‘œμ„ΈμŠ€λ₯Ό resume ν•œλ‹€.
β—¦
suspend 된 ν”„λ‘œμ„ΈμŠ€κ°€ μ—†μœΌλ©΄ 아무 일도 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€.
β€’
μƒμ‚°μž μ†ŒλΉ„μž λͺ¨λ‹ˆν„° μ½”λ“œ
β—¦
P(mutex), V(mutex) 처럼 락을 κ±Έκ³  ν•΄μ œν•˜λŠ” μ½”λ“œκ°€ μ‚¬λΌμ‘Œλ‹€.
β€’
μ‹μ‚¬ν•˜λŠ” μ² ν•™μž
test λ©”μ„œλ“œ μ•ˆμ˜ self[i].signal() 은 인접 μ² ν•™μžκ°€ putdown μ‹œ κΉ¨μ›Œμ£ΌκΈ° μœ„ν•œ μš©λ„