Condition Variable

condition_variable 연결

condition_variable은 이벤트 자체를 저장하지 않는다. 대기 조건은 공유 상태에 있고, wait는 그 상태를 mutex와 함께 다시 확인해야 한다.

01

조건을 상태로 둔다

큐가 비어 있지 않다, 종료 플래그가 켜졌다처럼 검사 가능한 값을 만든다.

02

같은 mutex로 보호한다

조건을 바꾸는 코드와 wait에서 조건을 읽는 코드가 같은 잠금을 사용해야 한다.

03

predicate wait를 쓴다

cv.wait(lock, predicate)는 가짜 깨움과 경쟁을 다시 검사해 준다.

unique_lock
wait에 필요 condition_variable이 잠금을 풀고 다시 잡아야 하므로 lock_guard로는 부족하다.
wait 전에는 잠겨 있어야 한다.
notify_one
대기자 하나 깨움 작업 하나가 생겼을 때 소비자 하나만 깨우기에 적합하다.
항상 상태 변경과 함께 생각한다.
notify_all
모든 대기자 깨움 종료 플래그처럼 모두가 조건을 다시 봐야 할 때 쓴다.
불필요한 깨어남 비용이 있다.
predicate
정답은 상태 알림은 힌트일 뿐이고 조건의 참거짓은 공유 상태가 결정한다.
while 루프와 같은 원리다.

상태 먼저 · 잠금 일관성 · 종료 점검

상태 먼저 notify만 호출하고 실제 predicate 상태를 바꾸지 않는 코드가 없는가.
잠금 일관성 조건을 읽고 쓰는 모든 경로가 같은 mutex를 쓰는가.
종료 대기 중인 스레드가 프로그램 종료 시 깨어나 빠져나갈 조건이 있는가.

predicate wait

std::unique_lock<std::mutex> lock(m);
cv.wait(lock, [&] { return !queue.empty() || stopped; });
if (stopped && queue.empty()) return;
auto job = std::move(queue.front());