"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
👨💻 안녕하세요, 윌리 프로젝트의 윌리 입니다.
C++ 에서 std::condition_variable 은 무엇이며, 어떻게 활용할 수 있는지 간략히 알아보았습니다.

질문 >
C++ 에서 std::condition_variable 은 무엇이며, 어떻게 활용할 수 있나요?
답변 >
std::condition_variable란?
std::condition_variable은 C++ 표준 라이브러리에서 제공하는 동기화 도구입니다. 이를 사용하면 스레드 간의 통신을 효율적으로 구현할 수 있습니다. 주로 하나의 스레드가 특정 조건을 만족할 때까지 다른 스레드가 대기하고, 조건이 만족되면 이를 알리는 방식으로 동작합니다.
std::condition_variable의 주요 특징
- 대기와 알림:
- 한 스레드가 조건을 기다리는 동안 다른 스레드가 조건을 충족시킨 뒤 알림을 보냅니다.
- 조건이 충족되었을 때만 대기 중인 스레드가 실행됩니다.
- 뮤텍스와 함께 사용:
- std::condition_variable은 std::mutex(뮤텍스)와 함께 사용되어 데이터 접근을 보호합니다.
- 대기와 알림 과정에서 데이터 경쟁 조건(race condition)을 방지합니다.
- 잠재적인 스레드 절전:
- 조건이 충족되지 않은 경우, 대기 중인 스레드는 절전 상태로 전환됩니다.
- 이를 통해 CPU 자원을 절약할 수 있습니다.
사용 가능한 주요 멤버 함수
- wait():
- 호출한 스레드를 조건이 충족될 때까지 대기 상태로 만듭니다.
- 반드시 뮤텍스와 함께 사용해야 하며, 조건을 확인하는 람다를 인수로 전달할 수 있습니다.
- notify_one():
- 대기 중인 스레드 중 하나를 깨웁니다.
- notify_all():
- 대기 중인 모든 스레드를 깨웁니다.
std::condition_variable 사용법
1. 기본 예제: notify_one()
#include <iostream>
#include <thread>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; }); // 조건이 충족될 때까지 대기
std::cout << "Worker thread is running!" << std::endl;
}
int main() {
std::thread t(worker);
{
std::lock_guard<std::mutex> lock(mtx);
ready = true; // 조건 충족
}
cv.notify_one(); // 대기 중인 스레드 하나를 깨움
t.join();
return 0;
}
출력 예시:
Worker thread is running!
2. notify_all()로 여러 스레드 알림
#include <iostream>
#include <thread>
#include <condition_variable>
#include <vector>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker(int id) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return ready; }); // 조건 충족 대기
std::cout << "Worker thread " << id << " is running!" << std::endl;
}
int main() {
const int numThreads = 3;
std::vector<std::thread> threads;
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back(worker, i);
}
{
std::lock_guard<std::mutex> lock(mtx);
ready = true; // 조건 충족
}
cv.notify_all(); // 모든 대기 중인 스레드 깨움
for (auto& t : threads) {
t.join();
}
return 0;
}
출력 예시:
Worker thread 0 is running!
Worker thread 1 is running!
Worker thread 2 is running!
실제 활용 예제
3. 생산자-소비자 문제
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
std::queue<int> buffer;
const int bufferSize = 5;
std::mutex mtx;
std::condition_variable cv;
void producer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return buffer.size() < bufferSize; }); // 버퍼가 비면 생산 가능
buffer.push(i);
std::cout << "Produced: " << i << std::endl;
cv.notify_all(); // 소비자 알림
}
}
void consumer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !buffer.empty(); }); // 버퍼가 비어있지 않으면 소비 가능
int item = buffer.front();
buffer.pop();
std::cout << "Consumed: " << item << std::endl;
cv.notify_all(); // 생산자 알림
}
}
int main() {
std::thread prod(producer);
std::thread cons(consumer);
prod.join();
cons.join();
return 0;
}
출력 예시:
Produced: 0
Consumed: 0
Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
...
주의사항
- 스풉리엇(wait())의 잠금 해제와 재획득:
- wait()는 대기 중인 동안 뮤텍스를 잠금 해제하지만, 조건이 충족되면 뮤텍스를 다시 획득합니다.
- 조건 확인 필수:
- 대기 상태에서 깨어난 뒤에도 조건을 반드시 확인해야 합니다.
- 스레드 기아 문제 또는 허위 깨어남(spurious wakeup)을 방지하려면 cv.wait(lock, condition) 형태로 사용하는 것이 좋습니다.
- 뮤텍스와 조건 변수의 올바른 사용:
- std::condition_variable는 항상 std::mutex와 함께 사용해야 합니다. std::unique_lock<std::mutex>를 사용하는 것이 권장됩니다.
결론
std::condition_variable은 스레드 간의 동기화와 효율적인 통신을 위한 강력한 도구입니다. 이를 통해 스레드가 특정 조건을 만족할 때만 실행되도록 제어할 수 있습니다.
- 주요 활용:
- 생산자-소비자 패턴 구현.
- 스레드 풀 관리.
- 특정 조건 충족 시 이벤트 처리.
std::condition_variable은 멀티스레드 프로그램의 안정성과 효율성을 높이는 데 중요한 역할을 합니다. 이를 올바르게 사용하면 데이터 무결성을 유지하면서 스레드 간의 효율적인 협력을 구현할 수 있습니다.
🎬 유튜브 채널 🎬
위로그@WiLog
📢 안녕하세요, 위로그@WiLog 시청자 여러분, 저는 윌리(Willee) 입니다. 📢 위로그@WiLog 는 자기계발을 목적으로 하는 채널 입니다. 📢 오늘도 즐겁게~ 자신을 위한 계발을 함께 해보아요~ d^_^b 📌
www.youtube.com
🎬 치지직 채널 🎬
위로그 채널 - CHZZK
지금, 스트리밍이 시작됩니다. 치지직-
chzzk.naver.com
'프로그래밍' 카테고리의 다른 글
👨💻 [Windows] 마이크로소프트의 기술로 윈도우 응용 프로그램을 만든다면, 어떤 기술 스택으로 만들어야 할까요? (0) | 2025.01.23 |
---|---|
👨💻 [C++] C++ 에서 std::atomic_ 로 시작하는 데이터 타입들은 무엇이며, 어떻게 활용할 수 있나요? (0) | 2025.01.23 |
👨💻 [C++] C++ 에서 thread 의 joinable() 은 무엇이며, 어떻게 활용할 수 있나요? (0) | 2025.01.23 |
👨💻 [C++] C++ 에서 thread 의 join() 은 무엇이며, 어떻게 활용할 수 있나요? (0) | 2025.01.23 |
👨💻 [C++] C++ 에서 std::this_thread::get_id() 는 무엇이고, 어떻게 활용할 수 있나요? (0) | 2025.01.23 |