[C++]Condition Variable

강병우·2023년 8월 11일
0

Condition Variable

condition variable은 공유 변수 등을 사용하고 다른 스레드에게 통지하기 전까지 스레드를 대기 상태로 유지하도록 하는 동기화 클래스이다.

통지 요청 방식

  1. mutex를 획득한다

  2. 공유 변수 값을 변경한다.

  3. mutex를 반환한다.

  4. condition variable를 통해 대기중인 스레드에게 변경 사항을 통지한다.


    대기 동작 방식

  5. mutex를 획득한다.

  6. condition variablemutex를 등록하고 상태를 체크한다.

  7. 대기 상태로 진입한다. mutex를 반환하고 스레드 수행을 중지한다.

  8. condition variable이 통지되거나 시간이 만료되거나 거짓 통지가 발생하면 스레드는 대기 상태에서 깨어난다. mutex를 획득한다. 조건을 확인하고 거짓 통지라면 다시 대기 상태로 진입한다.

예제

#include "pch.h"
#include <iostream>
#include "CorePch.h"
#include <thread>
#include <atomic>
#include <mutex>
#include <windows.h>

mutex m;
queue<int32> q;
HANDLE handle;

// 참고) CV는 User-Level Object (커널 오브젝트X)
// 조건부 대기 !(이벤트에 조건성이 합쳐진 개념)
condition_variable cv;

void Producer()
{
	while (true)
	{
		// 1) Lock을 잡고
		// 2) 공유변수값을 수정
		// 3) Lock을 풀고
		// 4) 조건변수 통해 다른 쓰레드에게 통지
		{
			unique_lock<mutex> lock(m);
			q.push(100);
		}
		
	}

	cv.notify_one();	// wait 중인 쓰레드가 있으면 딱 1개를 깨운다.
	//::SetEvent(handle);
	//this_thread::sleep_for(100ms);
}

void Consumer()
{
	while (true)
	{
		// ::WaitForSingleObject(handle, INFINITE);
		unique_lock<mutex> lock(m);
		cv.wait(lock, []() { return q.empty() == false; });
		// 1) Lock을 잡고
		// 2) 조건 확인
		// -) 만족O => 빠져 나와서 이어서 코드 실행
		// -) 만족X => Lock을 풀어주고 대기 상태

		// 그런데 notify_one을 했으면 항상 조건식을 만족하는거 아닐까?
		// Spurious WeakUp (가짜 기상?)
		// notify_one할 때, Lock을 잡고 있는 것이 아니기 때문임. 
		
		// while (q.empty() == false)	// CV에서 조건 체크 중이기 때문에 생략 가능
		{
			int32 data = q.front();
			q.pop();
			cout << data << endl;
		}
	}
}


int main()
{
	// 커널 오브젝트
	// Usage Count
	// Signal (파란불) / Non-Signal (빨간불) << bool
	// Auto / Manual << bool

	handle = ::CreateEvent(NULL/*보안속성*/, FALSE/*bManualReset*/, FALSE/*binitialState*/, NULL);

	thread t1(Producer);
	thread t2(Consumer);

	t1.join();
	t2.join();

	::CloseHandle(handle);

}

0개의 댓글

관련 채용 정보