🎮
Event
January 07, 2024
Event
난 소중하니 직원한테 부탁 (갑질메타)
예제
mutex m;
queue<int32> q;
void Producer()
{
while(true)
{
{
unique_lock<mutex> lock(m);
q.push(100);
}
this_thread::sleep_for(10000ms);
}
}
void Consumer()
{
while(true)
{
{
unique_lock<mutex> lock(m);
if (q.empty() == false)
{
int32 data = q.front();
q.pop();
cout << data << endl;
}
}
}
}
int main()
{
thread t1(Producer);
thread t2(Consumer);
t1.join();
t2.join();
return 0;
}
- 생산자(
Producer
) 쓰레드는 10초 마다 한번씩 생산하고, 소비자(Consumer
) 쓰레드는 바쁜 대기를 통해 계속해서 CPU 코어를 점유함. - 한 번 데이터를 소비하기 위해 10초동안 코어를 점유하는 것은 너무나 비효율적임.
- 큐에 데이터가 들어올때 알려주는 무언가가 있으면 좋을 것 같다. =>
Event
Create Event
mutex m;
queue<int32> q;
void Producer()
{
while(true)
{
{
unique_lock<mutex> lock(m);
q.push(100);
}
::SetEvent(handle); //Event의 상태를 Signal로 변경
this_thread::sleep_for(10000ms);
}
}
void Consumer()
{
while(true)
{
::WaitForSingleObject(handle, INFINITE); //무한 대기 -> 초록불일때까지 기다림.
//auto 옵션이므로 여기서 다시 Signal이 빨간불로 바뀜.
//만약 manual 옵션이라면 ::ResetEvent(handle); 추가
{
unique_lock<mutex> lock(m);
if (q.empty() == false)
{
int32 data = q.front();
q.pop();
cout << data << endl;
}
}
}
}
HANDLE handle; //생산자, 소비자에서 사용 가능하게끔 전역으로 선언
int main()
{
//커널 오브젝트
handle = ::CreateEvent(NULL/*보안속성*/, FALSE/*auto reset*/, FALSE/*초기 상태*/, NULL/*이름*/);
thread t1(Producer);
thread t2(Consumer);
t1.join();
t2.join();
::CloseHandle(handle); //사용이 끝난 Handle은 수거를 하는 것이 바람직함.
return 0;
}
HANDLE CreateEventW(LPSECURITY lpEventAttributes, BOOL bManualReset, Bool bInitialState, LPCWSTR lpName)
Event
는 커널에서 만들어주기 때문에커널 오브젝트
라고도 불린다.- 커널에서 관리하는 오브젝트다.
- Usage Count : 해당 오브젝트를 사용중인 프로세스나 쓰레드의 수. 커널 오브젝트가 공통으로 가진다.
- Signal / Non-Signal : 파란불, 빨간불 << bool
- Auto / Manual : 예제에선 Auto
- HANDLE은 int와 같은 숫자를 의미한다. ex)10, 20, 33, …
- 일종의 번호표
- 다른곳에서 사용 가능
- 유저모드 <-> 커널모드 간 이동 떄문에 오버헤드가 발생함
- 굉장히 자주 발생하는 작업에는 부적절하다.
그러나 이 코드에는 문제점이 존재함. 문제점은 다음 ConditionVariable에서 알아보자.