(= Producer-Consumer Problem, 생산자 소비자 문제)
= 공유 버퍼의 크기가 유한한 환경에서 생기는 문제
생산자-소비자 문제
아래와 같이 공유버퍼에 두 종류의 프로세스가 있다.
Producer (buffer에 데이터 넣기)
Consumer (buffer에서 데이터 꺼내기)
언제 동기화문제가 발생하나 ?
자원에 대한 동시접근
Producer의 경우
Consumer의 경우
Bounded Buffer여서 발생하는 문제
자원의 관점에서
Producer
Consumer
Shared Data
Synchronized Variable
// - Producer
do {
produce an item in x
...
P(empty); // 빈 퍼버가 있는지 확인
P(mutex); // 있다면, lock을 건다
...
add x to buffer
...
V(mutex); // lock을 푼다
V(full); // full buffer의 개수 1 증가
}
// - Consumer
do {
P(full); // full 버퍼가 있는지 확인
P(mutex); // 있다면, lock을 건다
...
remove an item from buffer to y
...
V(mutex); // lock을 푼다
V(empty); // empty buffer의 개수 1 증가
...
consume the item in y
}
= reader와 writer 두 개의 프로세스가 DB를 공유하는 환경
Shared Data
Synchronized Variable
// - Writer
P(db); // writer가 들어가면 lock을 건다
...
writing DB is performed
...
V(db); // lock을 풀어줌
// - Reader
P(mutex); // readcount를 증가시키기 위한 lock 걸기
readcount++; // readcount 1 증가
if (readcount == 1) P(db); // 내가 처음 들어온 reader라면 DB lock 걸기
V(mutex); // readcount에 대한 lock 풀기
...
reading DB is performed
...
P(mutex); // readcount를 감소시키기 위한 lock 걸기
readecount--;
if (readcount == 0) V(db); // 내가 마지막 reader라면 DB lock 풀기
V(mutex); // readcount에 대한 lock 풀기
starvation 발생 가능
5명의 철학자는 생각하거나 / 밥을 먹는 두 가지 행위를 할 수 있다.
인접한 철학자끼리는 젓가락을 공유하고, 왼쪽과 오른쪽 젓가락 두 개를 획득해야 밥을 먹을 수 있다.
Synchronization variables
Philosopher i
do {
P(chopstick[i]); // 왼쪽 젓가락을 잡는 행위
P(chopstick[(i+1) % 5]); // 오른쪽 젓가락을 잡는 행위
...
eat(); // 밥 먹는 중..
...
V(chopstick[i]) // 왼쪽 젓가락 놓기
V(chopstick[(i+1) % 5]) // 오른쪽 젓가락 놓기
...
think();
}
= deadlock 가능성 (모든 철학자가 동시에 배가 고파져 왼쪽 젓가락을 집은 경우)
변수
enum { thinking, hungry, eating } state[5]; (상태표현)
semaphore self[5] = 0; (젓가락 두 개 확보 가능해 밥먹을 권리 부여)
semaphore mutex = 1; (상태를 동시에 바꾸지 못하도록 lock걸기)
// Philosopher i
do {
pickup(i);
eat();
putdown(i);
think();
}
void pickup(int i) {
P(mutex); // 상태 바꾸기 전 lock 걸기
state[i] = hungry; // hungry로 상태 변경
test(i); // 젓가락 둘 다 집을 수 있는지 테스트
V(mutex); // lock 풀고
P(self[i]); // 밥 먹을 수 있는 권리 해제(1->0)
}
void test(int i) {
if (state[(i+4)%5] != eating && state[i] == hungry && state[(i+1)%5] != eating) {// 양쪽 철학자가 먹고있지 않고 내가 배고플 때
state[i] = eating; // eating으로 상태 변경
V(self[i]); // 밥 먹을 수 있는 권리 부여(0->1)
}
}
void putdown(int i) {
P(mutex);
state[i] = thinking;
test((i+4)%5); // 혹시 나 땜에 못먹었는지 양쪽 철학자 테스트
test((i+1)%5);
V(mutex);
}
자료 출처