MMOServer

Event, Condition_Variable(C++)

이야기prog 2025. 3. 13. 18:30
#include "pch.h"
#include <thread>
#include <atomic>
#include <mutex>
#include <windows.h>

mutex m;
queue<int32> q;
HANDLE handle;
void Producer() {
	while (true) {

		{
			unique_lock<mutex> lock(m);
			q.push(100);
		}

		::SetEvent(handle);
		std::this_thread::sleep_for(100ms);
	}
}
void Consumer() {

	while (true) {

		::WaitForSingleObject(handle, INFINITE);
		//::ResetEvent(handle);
		unique_lock<mutex> lock(m);

		if (!q.empty()) {
			int32 data = q.front();
			q.pop();
			cout << data << endl;
		}
	}
}



int main() {

	handle = ::CreateEvent(NULL, FALSE, FALSE, NULL); // 보안적, signal auto or maunual, 초기 상태, 이름
	std::thread t1(Producer);
	std::thread t2(Consumer);

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

	::CloseHandle(handle);
	return 0;
}

커널모드에서 event를 생성하여 event의 상태가 signal상태라면  Consumer 함수의 WaitForSingleObject에서 빠져나오게 되고, non-signal 상태라면 커널 모드에서 thread가 대기하게 된다. 이렇게 함으로 cpu점유율을 줄일 수 있다.

 

#include "pch.h"
#include <thread>
#include <atomic>
#include <mutex>

mutex m;
queue<int32> q;
condition_variable cv;
void Producer() {
	while (true) {

		{
			unique_lock<mutex> lock(m);
			q.push(100);
		}
		cv.notify_one();
	}
}
void Consumer() {

	while (true) {

		unique_lock<mutex> lock(m);
		cv.wait(lock, []() {return !q.empty();});

			int32 data = q.front();
			q.pop();
			cout << data << endl;
	}
}



int main() {

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

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

	return 0;
}

전의 코드에서 api부분을 없애고, c++표준을 사용한 condition_variable로 event를 사용할 수 있다.

cv.notify_one()으로 대기중인 하나의 스레드를 실행 가능하게 하고, cv.wait부분에서 lock과 조건을 확인해서 스레드가 다시 대기하거나, 실행된다. cv.wait()의 동작 순서는 

  1. lock을 얻는 시도를 한다.
  2. lock을 얻었으면, 조건을 확인한다.
  3. 조건이 참이면 다음 코드를 이어서 수행하고, 거짓이면 lock을 풀고 대기 상태

만약에 대기상태가 되면, 다시 condition_variable에서 notify를 할 때까지 대기 상태가 되고, notify를 하면 대기 상태를 풀고 1번부터 다시 동작한다.

condition_variable을 사용할 때는 보통 lock을 잠구고 -> 공유 변수 값을 수정 -> lock을 풀고 -> notify로 사용한다.

'MMOServer' 카테고리의 다른 글

멀티스레드의 메모리 이슈  (0) 2025.03.13
Future(C++)  (0) 2025.03.13
SpinLock(C++)  (0) 2025.03.13
Mutex(C++)  (0) 2025.03.11
Atomic(C++)  (0) 2025.03.11