Bounded-Buffer PS
0x10. Problem
0x11. situation
WHO
-
Producer: 데이터를 생성해서 buffer에 넣는 entity
-
Consumer: buffer에서 데이터를 꺼내서 사용하는 entity
-
Buffer: fixed size를 가진 shared memory (queue 형태)
dynamics
-
Producer → buffer에 item push
-
Consumer → buffer에서 item pop
-
동시에 여러 producer/consumer가 접근 가능 (concurrent execution)
constraint
-
buffer가 가득 차면 → producer는 더 이상 넣으면 안됨
-
buffer가 비어 있으면 → consumer는 꺼낼 수 없음
0x12. aspect
0x20. IDEA
0x21. 두 종류의 제어를 분리해야 함.
-
Mutual Exclusion: 한 번에 한 execution(process/thread)만 buffer를 만지게 한다
-
resource availability control: 넣을 수 있을 때만 넣고, 꺼낼 수 있을 때만 꺼내야 함.
- -> empty개수, full 개수에 대한 정보 관리가 필요
0x30. Solution
0x31. w/ Semaphores
- 접근 제어(Mutual Exclusion)을 위해 binary semaphore를 사용
- bounded특성(resource availability control)을 관리하기 위해 integer semaphore를 사용
- empty개수 관리 -> empty buffer
- full 개수 관리 -> full buffer
IMPL
semaphore N_empty_buf = N;
semaphore N_full_buf = 0;
semaphore S_mutex = 1;
// producer
while (1) {
item = produce_item();
P(N_empty_buf);
P(S_mutex);
insert_item(item); // write to buf
V(S_mutex);
V(N_full_buf);
}
// consumer
while (1) {
P(N_full_buf);
P(S_mutex);
item = remove_item(); // read from buf
V(S_mutex);
V(N_empty_buf);
consume_item(item);
}
0x32. w/ monitor
IMPL
monitor BoundedBuffer {
Item buf[N];
int in = 0;
int out = 0;
int count = 0;
condition notFull;
condition notEmpty;
void produce() {
while (count == N) {
notFull.wait();
}
buf[in] = item;
in = (in + 1) % N;
count++;
notEmpty.signal();
}
// consumer
Item consume() {
Item item;
while (count == 0) {
notEmpty.wait();
}
item = buf[out];
out = (out + 1) % N;
count--;
notFull.signal();
return item;
}
}
void producer_thread() {
while (1) {
Item item = produce_item(); // 데이터 생성 (independent)
buffer.produce(item); // monitor 호출
}
}
void consumer_thread() {
while (1) {
Item item = buffer.consume(); // monitor 호출
consume_item(item); // 데이터 사용
}
}