반응형
std::condition_variable::wait
현재 쓰레드 뮤텍스의 잠금을 풀고 notifu_one() 또는 notify_all()을 기다립니다.
깨어나면, 뮤텍스를 다시 잠급니다.
다시말해, notify_xxx가 wait()보다 먼저 호출되면, 해당 쓰레드는 풀리지 않고, 영원히 기다리게 됩니다.
#include <iostream>
#include <mutex>
#include <queue>
static std::mutex sQueueLock;
static std::condition_variable sEvent;
static std::queue<int> sQueue;
void Consume()
{
while (true)
{
int val;
{
std::unique_lock<std::mutex> lock(sQueueLock);
sEvent.wait(lock);
val = sQueue.front();
sQueue.pop();
}
std::cout << val << std::endl;
}
}
void Produce()
{
std::unique_lock<std::mutex> lock(sQueueLock);
sQueue.push(1);
sEvent.notify_one();
}
int main()
{
std::thread producer(Produce);
std::thread consumer(Consume);
consumer.join();
producer.join();
return 0;
}
Predicate 변수를 활용해 잘못 깨어날 위험을 줄입니다. 잠긴 두 쓰레드 모두에서 접근할 수 있는 bool 변수의 역할을 합니다. 해당 문제를 해결한 예제는 아래와 같습니다.
#include <iostream>
#include <mutex>
#include <queue>
static std::mutex sQueueLock;
static std::condition_variable sEvent;
static std::queue<int> sQueue;
void Consume()
{
while (true)
{
int val;
{
std::unique_lock<std::mutex> lock(sQueueLock);
sEvent.wait(lock, [] {return !sQueue.empty(); });
val = sQueue.front();
sQueue.pop();
}
std::cout << val << std::endl;
}
}
void Produce()
{
std::unique_lock<std::mutex> lock(sQueueLock);
sQueue.push(1);
sEvent.notify_one();
}
int main()
{
std::thread producer(Produce);
std::thread consumer(Consume);
consumer.join();
producer.join();
return 0;
}
lock만 쓰는 것은 충분하지 않는 경우가 많습니다. 조건 변수가 신호를 받기 전에 대기 상태에 들어가는 것을 보장할 수 없을 수 있습니다. 이 떄, 항상 bool 조건과 lcok을 같이 활용해야 합니다. 위의 방식을 참조하여 구현하도록 하겠습니다.
반응형
'SW > C++' 카테고리의 다른 글
C++ : STL : find 알고리즘 구현 : 예제 (0) | 2020.04.01 |
---|---|
C++ : STL 알고리즘 : 종류, 예제, copy() 사용 방법 (0) | 2020.03.31 |
C++ : condition_variable, unique_lock : 개념, 정의, 활용 방법 (0) | 2020.03.29 |
C++ : std::scoped_lock : 예제, 사용법, 활용법, 실수 방지 방법 (0) | 2020.03.21 |
C++ : mutex (뮤텍스) : 예제, 사용법, 활용 방법 (0) | 2020.03.20 |