1. std::future와 std::promise
C++11에서 도입된 비동기 프로그래밍을 위한 도구
std::future : 비동기 작업의 결과를 나타내는 객체. 미래의 어느 시점에 값이 설정될 것임을 나타낸다.
std::promise : future에 값을 설정하는 쓰기 가능한 끝점
이 둘은 서로 쌍을 이루어 동작하며, 다른 스레드에서 실행되는 작업의 결과를 안전하게 전달할 수 있게 한다.
ex)
#include <iostream>
#include <future>
#include <thread>
using namespace std;
void SetValue(promise<int>& p) {
this_thread::sleep_for(chrono::seconds(2));
p.set_value(10);
}
int main() {
promise<int> p;
future<int> f = p.get_future();
thread t(set_value, ref(p));
cout << "대기중.." << endl;
cout << "값: " << f.get() << endl;
t.join();
}
2. std::packaged_task
함수나 callable 객체를 래핑하여 그 실행 결과를 future 객체를 통해 얻을 수 있게 해주는 클래스 템플릿
ex)
#include <iostream>
#include <future>
#include <thread>
using namespace std;
int Computation(int a, int b) {
this_thread::sleep_for(chrono::seconds(2));
return a + b;
}
int main() {
packaged_task<int(int, int)> task(ComputeSum);
future<int> f = task.get_future();
thread t(move(task), 10, 20);
cout << "대기중.." << endl;
cout << "값 : " << f.get() << endl;
t.join();
}
3. std::async
std::async는 함수를 비동기적으로 실행하고 결과를 future 객체로 반환하는 인터페이스를 제공한다.
실행정책:
std::launch::async : 새 스레드에서 함수를 실행
std::launch::deferred : 결과가 필요할 때까지 함수 실행을 지연
std::launch::async | std::launch::deferred : 실행 방식을 시스템이 결정
ex)
#include <iostream>
#include <future>
#include <chrono>
using namespace std;
long Fibonacci(unsigned int n) {
if (n < 2) return n;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
int main() {
cout << "Fibonacci 계산" << endl;
auto start = chrono::high_resolution_clock::now();
future<long> f = async(launch::async, Fibonacci, 40);
cout << "-다른 작업 실행-" << endl;
long result = f.get();
auto end = chrono::high_resolution_clock::now();
chrono::duration<double> diff = end - start;
cout << "\n결과\n" << "값 : " << result << endl;
cout << "시간 : " << diff.count() << " 초" << endl;
}
위 예제에서 Fibonacci 함수는 비동기로 실행되며, 메인 스레드는 결과를 기다리는 동안 다른 작업을 수행할 수 있다.
4. std::future의 추가 기능
std::future 클래스의 메서드:
wait() : 결과가 준비될 때까지 블록
wait_for() : 지정된 시간 동안 결과를 기다림
wait_until() : 지정된 시간까지 결과를 기다림
valid() : future 객체가 공유 상태와 연관되어 있는지 확인
ex)
#include <iostream>
#include <future>
#include <chrono>
using namespace std;
int Computation() {
this_thread::sleep_for(chrono::seconds(3));
return 10;
}
int main() {
auto future = async(launch::async, Computation);
cout << "대기중.." << endl;
future_status status = future.wait_for(chrono::seconds(2));
if (status == future_status::ready) {
cout << "값 : " << future.get() << endl;
}
else if (status == future_status::timeout) {
cout << "결과 대기중.." << endl;
cout << "값 : " << future.get() << endl;
}
}
5. std::shared_future
std::future와 달리 복사가 가능하며 여러 스레드에서 동일한 비동기 결과를 기다릴 수 있다.
ex)
#include <iostream>
#include <future>
#include <vector>
using namespace std;
int SetValue() {
this_thread::sleep_for(chrono::seconds(2));
return 10;
}
void Print(shared_future<int> f, int id) {
cout << "스레드 " << id << " 대기중.." << endl;
cout << "스레드 " << id << " 값 : " << f.get() << endl;
}
int main() {
promise<int> p;
shared_future<int> shared_future = p.get_future().share();
vector<thread> threads;
for (int i = 0; i < 3; ++i) {
threads.emplace_back(Print, shared_future, i);
}
thread th(
[&p](){p.set_value(SetValue());}
);
for (auto& t : threads) {
t.join();
}
th.join();
}
'멀티스레딩' 카테고리의 다른 글
고급 동기화 기법 (1) | 2024.10.16 |
---|---|
Condition Variable (0) | 2024.10.16 |
스핀락(Spinlock) (0) | 2024.10.12 |
데드락(Deadlock) (1) | 2024.10.07 |
동기화 기법: Mutex (0) | 2024.10.05 |