본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : std::async (11)

by snowoods 2025. 10. 21.

Modern C++

 

std::async

 

개요

std::async는 함수를 비동기적으로 실행하고 그 결과를 std::future 객체를 통해 얻을 수 있게 해주는 함수 템플릿입니다. std::thread와 달리 스레드 풀을 활용하여 스레드 생성 오버헤드를 줄일 수 있으며, 함수의 반환값을 쉽게 얻을 수 있는 장점이 있습니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++11 : std::async, std::future 도입

 

내용 설명

std::async는 함수(또는 호출 가능한 객체)를 인자로 받아 비동기적으로 실행합니다. std::asyncstd::future 객체를 반환하는데, 이 future 객체를 통해 비동기 작업의 결과를 얻거나 작업이 완료될 때까지 대기할 수 있습니다.

std::async는 실행 정책(launch policy)을 지정할 수 있습니다.

  • std::launch::async: 새로운 스레드를 생성하여 작업을 비동기적으로 실행합니다.
  • std::launch::deferred: std::futureget()이나 wait()가 호출될 때까지 함수의 실행을 지연시킵니다. 실제로는 비동기 실행이 아니라 동기 실행처럼 동작할 수 있습니다.
  • std::launch::async | std::launch::deferred (기본값): 구현이 실행 시점에 가장 적절한 방식을 선택하도록 허용합니다. 스레드 풀을 활용하거나, 지연 실행을 하는 등 유연하게 동작합니다.

std::future 객체의 get() 멤버 함수를 호출하면 비동기 작업이 완료될 때까지 현재 스레드를 블로킹하고, 작업이 완료되면 결과값을 반환합니다. get()은 단 한 번만 호출할 수 있습니다.

 

예제 코드

#include <future>
#include <iostream>
#include <thread>

int function(const int input)
{
    std::cout << "function thread id: " << std::this_thread::get_id() << '\n';
    std::cout << "input: " << input << '\n';

    return input * 2;
}

int main()
{
    std::cout << "main thread id: " << std::this_thread::get_id() << '\n';

    int input = 1;
    auto handle = std::async(std::launch::async, function, input);

    // ... 다른 작업 수행 ...

    auto result = handle.get();
    std::cout << "result: " << result << '\n';

    return 0;
}

 

실행 결과

main thread id: 140732315582464
function thread id: 140732315582465
input: 1
result: 2

스레드 ID는 실행할 때마다 달라질 수 있습니다.

활용팁

  • 반환값이 필요한 비동기 작업: std::thread는 반환값을 직접 처리하기 번거롭지만, std::asyncstd::future를 통해 간단하게 결과를 얻을 수 있어 유용합니다.
  • 스레드 관리 단순화: std::async를 사용하면 스레드의 생성, 소멸, 예외 처리 등을 직접 관리할 필요가 줄어들어 코드가 간결해집니다. std::async가 반환한 future 객체가 소멸될 때, 비동기 작업이 완료될 때까지 대기하므로 join()을 명시적으로 호출할 필요가 없습니다. (단, 이는 때로 의도치 않은 성능 저하를 유발할 수 있으므로 주의해야 합니다.)
  • 실행 정책 선택: std::launch::async를 명시적으로 사용하여 새로운 스레드에서 즉시 실행되도록 보장하거나, std::launch::deferred를 사용하여 필요할 때만 실행하도록 지연시킬 수 있습니다. 요구사항에 맞는 실행 정책을 선택하여 사용하세요.