Event
1. 커널 오브젝트
2. 다른 프로그램과 동기화 가능
커널에서 관리하고 있는 객체로 나중에 여러 프로그램에서의 동기화 작업할때 커널 오브젝트를 사용하면 프로세스들 끼리 동기화 가능 기존 만들었던 spin_lock은 유저 단에서 가능하지만 커널은 system 단에서 가능
Signal(파란불), Non_Signal (빨간불) << bool
Auto/Manual << bool
//CreateEvent : windows.h
//Handle 많은 Event중에 구별하는 식별자
//bManualReset를 False로 설정해주었기 때문에 자동으로 Non-signal로 바뀜
HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
Conditional Variable
1. 유저 오브젝트
2. 같은 프로그램내에서만 가능
::cv.notify_one();
while (true) {
unique_lock<mutex> lock(m);
//wait사용할때는 "조건"이 필요하기 때문에 무조건 uniqueLock을 사용해야 한다.
//notify_one 했으면 조건 안보고 그냥 깨워도 되는거 아니냐?
//중간에 누가 가로챌 수 있기 때문에 조건을 걸어서 다시 확인해주어야한다.(Spurious Wakeup 가짜 기상 상태 발생 가능성있음)
cv.wait(lock, []() { return q.empty() == false; });
Event의 경우 실제로 Signal 상태와 Non-Signal 상태를 가지며, WaitForSingleObject 함수를 사용하여 이벤트의 신호를 기다립니다. INFINITE 옵션을 사용하면 신호가 발생할 때까지 무한정으로 대기할 수 있습니다. 이것은 다른 작업으로의 컨텍스트 스위치를 막을 수 있으나, 신호를 기다리는 동안 해당 스레드가 잠들어서 자원을 사용하지 않게 됩니다. 이는 CPU 자원의 측면에서는 효율적일 수 있지만, 해당 스레드가 수행 해야 할 다른 작업들에 대해 반응하지 못한다는 단점이 있습니다.
Conditional Variable은 스레드 간의 동기화를 위한 대안으로 제공되며, 특정 조건(Condition)이 충족됐을 때 대기 중인 스레드를 깨우는 메커니즘으로 동작합니다. cv.notify_one();을 호출하면 대기 중이던 스레드 중 하나를 깨워 작업을 계속하게 합니다. 이 메커니즘은 스레드가 불필요하게 대기 상태를 유지하는 것을 방지하고, 필요한 시점에만 작업을 수행하도록 하여 자원을 더 효율적으로 사용할 수 있도록 도와줍니다.
Event는 하드웨어 또는 운영체제 수준의 동기화 객체를 사용하여 구현되고, 스레드를 대기 시켰다가 이벤트를 세팅함으로써 깨우는 반면, Conditional Variable은 라이브러리 수준에서 제공되는 보다 높은 추상화된 동기화 메커니즘입니다. 두 방법 모두 자원을 손해 볼 수 있다기보다는, 특정 상황에서 더 적절하게 사용될 수 있는 동기화 방식을 제공하는 것입니다.