티스토리 뷰

프로그래밍/C++

조건변수

에어버스 2023. 8. 5. 14:58

조건 변수는 메시지를 통한 스레드 동기화에 사용된다.
이때 condition_variable 헤더가 필요하다.

한 스레드가 메시지 발신자 역활을 하면 다른 스레드는 수신자가 된다.
수신자는 발신자가 보낸 알림을 기다리게 된다.

조건 변수의 전형적인 쓰임새는 발신자->수신자 또는 생산자>소비자 작업 흐름이다.

조건 변수는 메시지 발신자뿐만 아니라 수진자도 될 수 있다.

cv.notify_one() : 대기하고 있는 스레드에게 알림을 보낸다.
cv.notify_all() : 대기하고 있는 스레드 전체에게 알림을 보낸다.
cv.wait(lock, ...) : std::unique_lock 을 받고 알림을 기다린다.
cv.wait_for(lock, relTime, ...) : std::unique_lock 을 받고 어떤 기간 동안 알림을 기다린다.
cv.wait_until(lock, absTime, ...) : std::unique_lock 을 받고 어떤 시점까지 알림을 기다린다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
 
std::mutex mutex_;
std::condition_variable condVar;
 
bool dataReady{ false };
 
void doTheWork() {
    std::cout << "PRocessing shared data." << std::endl;
}
 
void waitingForWork() {
    std::cout << "Worker : Wating for work." << std::endl;
    std::unique_lock<std::mutex> lck(mutex_); // 수신자는 unique_lock 필요
    
    // dataReady 값이 true면 조건 변수는 뮤텍스를 잠김 해제하고 그 다음 과정을 진행
    // dataReady 값이 false 면 조건 변수는 뮤텍스를 잠김 해제하고 다시 대기 상태로 들어간다.
    condVar.wait(lck, [] { return dataReady; });     
 
    doTheWork();
    std::cout << "Work done." << std::endl;
}
 
void setDataReady() {
    {
        std::lock_guard<std::mutex> lck(mutex_); // 발신자는 잠김과 해제를 한번만 호출하기 때문에 lock_guard 로 충분
        dataReady = true;
    }
    std::cout << "Sender : Data is ready." << std::endl;
    condVar.notify_one();
}
 
 
int main()
{
    std::cout << std::endl;
 
    std::thread t1(waitingForWork);
    std::thread t2(setDataReady);
 
    t1.join();
    t2.join();
    std::cout << std::endl;
}
cs

21행 : wait 가 처음 호출될때는 wait 호출은 뮤텍스를 잠그고 []{ return dataReady; } 하는 프레디킷(predicate) 이 true 인지 확인한다.
dataReady 값이 true 일 경우, 조건 변수는 뮤텍스를 잠김 해제하고 그 다음 과정을 진행하고
dataReady 값이 false 면 조건 변수는 뮤텍스를 잠김 해제하고 다시 대기 상태로 들어간다.

false 인 경우 대기 상태에서 발신자가 dataReady 값을 true 로 변경하고 메시지(알림)를 보낸 경우 
다시 wait 호출하면 대기하는 스레드가 알림을 받고 뮤텍스 잠그고 프레디킷을 확인후 false 면 다시 대기, true 면 대기상태에서 털출한다.

실행결과>

Sender, Worker 바뀔 수 있음.

만약, 아래 그림과 같이 프레디킷 값이 없으면 수진자(Worker) 스레드가 먼저 실행되면 대기 상태에서 빠져 나오지 못하는 문제가 발생할 수 있다.

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31