CS/C++
[Mastering C++ Programming] - Condition variable
sliver__
2022. 12. 9. 15:59
728x90
- 조건 변수 동기화 프리미티브는 둘 이상의 스레드가 서로 통신하고 특정 신호 또는 이벤트를 수신할 때만 진행해야 하는 경우에 사용됩니다.
- 특정 신호나 이벤트를 기다리는 스레드는 신호나 이벤트를 기다리기 전에 뮤텍스를 획득해야 합니다.
- 생산자/소비자 문제가 있는 조건 변수의 사용 사례를 이해해 봅시다.
- PRODUCER와 CONSUMER라는 두 개의 스레드를 생성하겠습니다.
- PRODUCER 스레드는 대기열에 값을 추가하고 CONSUMER 스레드에 알립니다.
- CONSUMER 스레드는 Producer의 알림을 기다립니다.
- Producer 스레드에서 알림을 받으면 CONSUMER 스레드는 대기열에서 항목을 제거하고 인쇄합니다.
- 여기에 표시된 Thread.h 헤더가 조건 변수와 뮤텍스를 사용하는 방법을 이해해 보겠습니다.
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <string>
using namespace std;
enum ThreadType {
PRODUCER,
CONSUMER
};
class Thread {
private:
static mutex locker;
static condition_variable untilReady;
static bool ready;
static queue<int> appQueue;
thread *pThread;
ThreadType threadType;
bool stopped;
string name;
void run();
public:
Thread(ThreadType typeOfThread);
~Thread();
void start();
void stop();
void join();
void detach();
};
#include "Thread.h"
mutex Thread::locker;
condition_variable Thread::untilReady;
bool Thread::ready = false;
queue<int> Thread::appQueue;
Thread::Thread( ThreadType typeOfThread ) {
pThread = NULL;
stopped = false;
threadType = typeOfThread;
(CONSUMER == typeOfThread) ? name = "CONSUMER" : name = "PRODUCER";
}
Thread::~Thread( ) {
delete pThread;
pThread = NULL;
}
void Thread::run() {
int count = 0;
int data = 0;
while ( 1 ) {
switch ( threadType ) {
case CONSUMER:
{
cout << name << " waiting to acquire mutex ..." << endl;
unique_lock<mutex> uniqueLocker( locker );
cout << name << " acquired mutex ..." << endl;
cout << name << " waiting for conditional variable signal..." << endl;
untilReady.wait ( uniqueLocker, [] { return ready; } );
cout << name << " received conditional variable signal ..." << endl;
data = appQueue.front( ) ;
cout << name << " received data " << data << endl;
appQueue.pop( );
ready = false;
}
cout << name << " released mutex ..." << endl;
break;
case PRODUCER:
{
cout << name << " waiting to acquire mutex ..." << endl;
unique_lock<mutex> uniqueLocker( locker );
cout << name << " acquired mutex ..." << endl;
if ( 32000 == count ) count = 0;
appQueue.push ( ++ count );
ready = true;
uniqueLocker.unlock();
cout << name << " released mutex ..." << endl;
untilReady.notify_one();
cout << name << " notified conditional signal ..." << endl;
}
break;
}
}
}
void Thread::start( ) {
pThread = new thread ( &Thread::run, this );
}
void Thread::stop( ) {
stopped = true;
}
void Thread::join( ) {
pThread->join( );
}
void Thread::detach( ) {
pThread->detach( );
}
#include "Thread.h"
int main ( ) {
Thread producer( ThreadType::PRODUCER );
Thread consumer( ThreadType::CONSUMER );
producer.start();
consumer.start();
producer.join();
consumer.join();
return 0;
}
++ Reference )
https://dydtjr1128.github.io/cpp/2020/04/05/Cpp-lock.html
C++ 락(std::lock, std::unique_lock, std::lock_guard, condition_variable...) - dydtjr1128's Blog
Intro std에 존재하는 lock 방법들은 운영체제 단에서 지원하는 크리티컬 섹션을 래핑한 mutex를 기반으로 개발자가 쉽게 락을 걸 수 있도록 도와줍니다. 앞서 배운...
dydtjr1128.github.io
https://jjeongil.tistory.com/1003
C++ : condition_variable::wait() : 사용법, 주의사항, 예제, 활용 방법
std::condition_variable::wait 현재 쓰레드 뮤텍스의 잠금을 풀고 notifu_one() 또는 notify_all()을 기다립니다. 깨어나면, 뮤텍스를 다시 잠급니다. 다시말해, notify_xxx가 wait()보다 먼저 호출되면, 해당 쓰레드
jjeongil.tistory.com
728x90