empty = N // 빈 칸 수 (카운팅)
full = 0 // 찬 칸 수 (카운팅)
mutex = 1 // 버퍼 보호 (이진)
생산자: wait(empty); wait(mutex); put(); signal(mutex); signal(full);
소비자: wait(full); wait(mutex); get(); signal(mutex); signal(empty);
signal(full)하면 소비자가 깨어난다 (A가 signal, B가 wait)wait(mutex)를 wait(empty) 보다 먼저 하면 데드락이 발생한다 (버퍼 락을 쥔 채 빈 칸을 기다림)// 첫번째 reader가 들어올 때 write 락을 잠그고,
// 마지막 reader가 나갈 때 write 락을 풀어준다
// rc : 읽기 카운터
read: lock(rc_mutex); rc++; if (rc==1) wait(rw); unlock(rc_mutex);
... 읽기 ...
lock(rc_mutex); rc--; if (rc==0) signal(rw); unlock(rc_mutex);
write: wait(rw); ... 쓰기 ... signal(rw);
DB의 공유 락(S) / 배타 락(X) 의 모델이다
철학자들이 원탁에 앉아 있고, 젓가락은 각 철학자의 왼쪽에 하나씩 있다.
식사를 하려면 양쪽 젓가락이 필요하다.
이때 모두가 왼쪽을 먼저 집고 오른쪽을 기다리면, 각자 젓가락 하나씩 쥔 채 서로를 영원히 기다리게 된다.
→ 데드락(순환 대기) 발생
뒤에 나옴
| 개념 | Java |
|---|---|
| 모니터 (자동 상호배제 + 조건변수) | synchronized + wait() / notify() |
| 뮤텍스 (소유권·재진입) | ReentrantLock |
| 세마포 (카운팅/신호) | java.util.concurrent.Semaphore |
| Reader-Writer | ReentrantReadWriteLock, StampedLock |
| 원자적 명령 (CAS) | AtomicInteger 등 Atomic* |
| 가시성·순서 | volatile, happens-before |
SELECT ... FOR UPDATE) : 데이터를 먼저 잠그고 접근 (뮤텍스)@Version) : 데이터를 잠그지 않고, 커밋 시 버전 비교로 충돌 탐지 후 롤백 (CAS / ABA 해법)pthread_mutex, pthread_cond 등이 그 위에 세워진 POSIX 표준 도구