<출처> [생산자와 소비자 문제](https://github.com/kangtegong/self-learning-cs/tree/main/producer_consumer)
이 곳에 첨부된 producer_consumer.cpp는 Chapter 12에서 언급한 대표적인 동기화 문제를 간단히 코드로 구현한 것입니다.
코드는 크게 produce
라는 함수를 10만번 실행하는 producer
스레드와
consume
이라는 함수를 10만번 실행하는 consumer
스레드로 이루어져 있습니다.
std::thread producer(produce);
std::thread consumer(consume);
그리고 producer
와 consumer
가 실행하기 전 총 합계에 해당하는 sum
을 출력하고,
실행한 이후 총 합계를 출력합니다.
std::cout << "초기 합계: " << sum << std::endl;
std::thread producer(produce);
std::thread consumer(consume);
producer.join();
consumer.join();
std::cout << "producer, consumer 스레드 실행 이후 합계: " << sum << std::endl;
produce
는 큐에 임의의 값(1)을 총 합계를 1 증가시키는 것을 10만번 반복하는 코드이고,
void produce() {
for(int i = 0; i < 100000; i++) {
//q.push(1);
sum++;
}
}
consume
은 큐의 값을 하나 뺴낸 뒤 총 합계를 1 감소시키는 것을 10만번 반복하는 코드입니다.
void consume() {
for(int i = 0; i < 100000; i++) {
//q.pop();
sum--;
}
}
위 코드는 얼핏 보면 아무런 문제가 없어 보일지 모르나 실행하면 예상치 못한 결과를 초래합니다.
큐에 값을 넣고 빼는 코드 (q.push(1)
, q.pop()
)을 포함하여 실행하면 에러가 발생하고,
이를 주석 처리하고 실행한다고 해도 실행 후 합계는 0이 아닌 전혀 다른 값이 됩니다.
큐에 값을 넣고 빼는 코드를 포함하여 실행하면 에러가 발생하는 이유는,
producer와 consumer 사이에 레이스 컨디션이 발생하여
큐에 아무것도 값이 남아있지 않았음에도 불구하고 값을 빼내려 했기 때문입니다.
공유 자원(shared resource) : 문제의 예시에서 동시에 실행되는 프로세스들은 전역 변수 ‘잔액’, ‘총합’ 이라는 공동의 자원을 두고 작업
임계 구역(critical section) : 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
레이스 컨디션(race condition) : 임계 구역은 두 개 이상의 프로세스가 동시에 실행되면 안 되는 영역인데, 잘못실행해서 여러 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 경우
예 : 손님 - 프로세스 / 탈의실 - 임계구역
뮤텍스 락(Mutex lock; MUTual EXclusion lock) : 상호 배제를 위한 동기화 도구, 동시에 접근해서는 안 되는 자원에 동시에 접근하지 않도록 만드는 도구
바쁜 대기(busy wait) : 마치 탈의실 문이 잠겨 있는지 쉴 새 없이 반복하며 확인해 보는 것
뮤텍스 락보다 조금 더 일반화된 방식의 동기화 도구
탈의실(공유자원, 임계구역)이 여러 개 일 때 사용 가능
철도 신호기에서 유래한 단어
세마포의 잘못사용될 경우를 보완하여 현대에 등장한 동기화 도구
세마포보다 사용자가 사용하기 더 편리함
<참고> [동기화](https://github.com/kangtegong/self-learning-cs/tree/main/synchronization)
p.363 - 1번 문제
Ch.12(12-1) 임계 구역, 상호 배제 개념을 정리하기
공유 자원 중에는 두 개 이상의 프로세스를 동시에 실행하면 문제가 발생하는 자원이 있는데, 이런 자원에 접근하는 코드 영역
한 프로세스가 임계 구역에서 작업 중이면 다른 프로세스가 임계 구역에 들어갈 수 없도록 제어하는 것