Program Language/C & C++

[C++] condition_variable

야곰야곰+책벌레 2021. 10. 5. 19:14
728x90
반응형

  thread를 수행할 때 때로는 다른 thread의 작업을 기다려야 할 때가 있다. 이때 condition_varialbe을 사용하면 thread를 block 할 수 있다. block 조건은 timeout을 설정할 수 도 다른 thread를 통해 설정할 수도 있다.

 

condition_variable은 다음과 같은 method를 제공한다.

notify_one : 해당 조건 변수를 기다리고 있는 thread 중 한 개의 thread를 깨운다.
notify_all : 해당 조건 변수를 기다리고 있는 모든 thread를 깨운다.

thread는 상기 method 이외에 timeout에 의해서 깨어날 수도 있다.

 

#include <mutex>
#include <future>
#include <iostream>
using namespace std;

mutex g_mutex;
bool  g_busyFlag = false;
condition_variable g_busyCV;

void OnThread1()
{
	cout << "get text:" << endl;
	cin.get();

	lock_guard<mutex> lock(g_mutex);
	g_busyFlag = true;
	g_busyCV.notify_one();
}

void OnThread2()
{
	std::unique_lock<mutex> lock(g_mutex);
	g_busyCV.wait(lock, []() -> bool { return g_busyFlag; });
	cout << "done" << endl;
}
int main()
{
	auto f1 = async(OnThread1);
	auto f2 = async(OnThread2);

	f1.get();
	return 0;
}

thread 사이 조건을 만들기 위하려면 다음과 같은 작업이 필요하다.

1. thread 상태를 나타내는 flag ( g_busyFlag)

2. mutex ( g_mutex)

3. condition_variable ( g_busyCV)

 

OnThread1()에서 mutex를 lock 하고 g_busyFlag를 갱신한다. unlock 조건을 정한다. ( notify_one() ) 조건 변수를 통해 알려주는 것 자체는 lock이 필요 없다.

 

std::unique_lock<mutex> lock(g_mutex);
g_busyCV.wait(lock, []() -> bool { return g_busyFlag; });

wait()의 사용법을 알아보자.

g_busyFlag를 인자로 가지는 unique_lock과 callable 객체를 전달한다.

여기서 callable 객체는 조건을 이중으로 검사할 때 사용한다. (spurious wakeup 때문)

spurious wakeup : POSIX나 모든 OS에서 signmal을 줬을 때 하나만 깨어나는 것이 아니라 동시에 여러 wait condition이 깨어날 수 있는 것을 말한다. 이는 OS의 performance 이슈 때문에 개발자 영역으로 남겨져 있다. 물론, Java에서도 마찬가지다.

이를 해결하기 위해서 wait 조건을 줄 때 guardian condition을 줘야 한다. 
while (guardian condtion) { wait(); }

여기서는 lock_guard가 아닌 unique_lock을 써야 한다는 점에 주의해야 한다. 내부적으로 wait()가 락을 풀었다가 다시 잠가주기 때문이다. 이런 방식으로 데이터가 도착할 때까지 기다리는 것은 future을 써서 구현하는 것이 더 나은 예가 될 수 있다.

728x90
반응형

'Program Language > C & C++' 카테고리의 다른 글

[C++] result_of  (0) 2021.10.06
[C++] Callable  (0) 2021.10.06
[C++] noexcept  (10) 2021.10.01
[C++] atomic  (6) 2021.10.01
[C++] explicit 키워드  (0) 2021.10.01