작성
·
129
0
//Producer
while(true)
{
{
unique_lock<mutex> lock(m);
q.push(100);
}
cv.notify_one();
}
//Consumer
while(true)
{
unique_lock<mutex> lock(m);
cv.wait(lock,[](){return q.empty()==false;});
{
int32 data = q.front();
q.pop();
cout<<data<<endl;
}
}
1. Producer에서 cv.notify_one(); 을 한 뒤 Consumer의 cv.wait가 깨어나기 전에 Producer가 unique_lock<mutex> lock(m); 을 걸면 pop을 하지 못하고 queue에 데이터가 연속으로 쌓이는 경우가 있나요?
2. 디버깅을 찍어보니 cv.wait가 처음 수행되었을 때는 cv.notify_one() 없이도 그냥 깨어나던데 cv.wait는 notify를 해줬을 경우만 깨어나지 않나요?
ex) 스레드 Producer, Consumer을 모두 실행 직후 최초 q.push 이후 notify_one 없이 wait가 깨어나 data를 cout 함.
3. notify_one 해줬을 때 cv.wait의 [](){return q.empty()==false;} 조건이 충족되지 않았을 때 대기를 하는데(queue에 아무것도 없는 상태)
이때, queue 에 push를 해주면 별도의 반복 notify_one 작업 없이 바로 깨어나나요?
디버깅을 해보니 notify_one을 걸고 조건 실패하여 대기중일때 queue에 push를 해주니 꺠어나는것 같았습니다.
notify_one은 1회성으로 바로 리턴하고 끝인줄 알았는데 Count가 하나 증가하여 queue에 data가 쌓일때까지 대기하는? 개념인지 궁금합니다.
답변 1
1
1. 네 그렇습니다.
2. 꼭 그렇진 않고, 구조상 깨어나서 허탕칠 가능성도 있습니다. 이를 전문적으로 spurious wakeup이라고 합니다.
https://en.wikipedia.org/wiki/Spurious_wakeup
3. 그 정도로 스마트하게 동작하진 않구요. 깨어났을 때 허탕치고 다시 잠들면, 다시 깨워줘야 합니다.
물론 2번에서처럼 중간 중간에 자연스럽게(?) 잠에서 깨는 경우도 있으니
너무 완벽하게 구조를 이해하려 할 필요는 없습니다.