본문 바로가기
💻 programming/c++

[c++] thread vs task (thread 와 async)

by 연구원-A 2021. 8. 4.
반응형

thread와 task는 사용 목적과 추상화 정도가 다르다

thread는 원시적인 병렬처리 방법이고, thread를 사용해 task는 데이터를 동기화하는 방법이다

 

⭐ 다시 말하면 데이터를 동기화 할 때는 굳이 개발자가 직접 thread를 생성하고, mutex를 이용하기 보다는

⭐ c++에서 제공하는 task를 이용하는 것이 좋다

⭐ 심지어 task를 이용할 때 thread를 생성할 수도 있고, 필요하면 생성하지 않고 동기화 할 수도 있다.

 

  • thread는 말그대로 병렬처리를 위한 흐름을 생성하고 제어하기 위한 기본적인 함수를 제공한다 (join, detach 등)
  • async와 같은 task는 promise-future 사이에 통신 흐름을 만든다
    • future에서 get 함수를 호출하여 promise와 동기화를 수행한다
    • 동기화 과정에서 thread 생성 여부는 aynsc에 전달하는 인자에 따라 다르게 동작한다
      • std::launch::async: async 함수 템플릿을 호출하면 바로 thread를 생성해서 인자로 전달된 함수를 실행한다 (enable asynchronous evaluation)
      • std::launch::deferred: async 함수가 반환한 std::future 객체의 get 함수가 호출되면 함수를 실행다 (enable lazy evaluation; thread가 새로 생성되지는 않음)

 

task의 데이터 채널 역할

 

이외에도 포함해야하는 헤더, 쓰레드 생성 여부 등이 각각 다르다.

cf. async를 이용한 동기화 예제 코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
#include <string>
#include <mutex>
 
std::mutex m;
struct X {
    void foo(int i, const std::string& str) {
        std::lock_guard<std::mutex> lk(m);
        std::cout << str << ' ' << i << '\n';
    }
    void bar(const std::string& str) {
        std::lock_guard<std::mutex> lk(m);
        std::cout << str << '\n';
    }
    int operator()(int i) {
        std::lock_guard<std::mutex> lk(m);
        std::cout << i << '\n';
        return i + 10;
    }
};
 
template <typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{
    auto len = end - beg;
    if (len < 1000)
        return std::accumulate(beg, end, 0);
 
    RandomIt mid = beg + len/2;
    auto handle = std::async(std::launch::async,
                             parallel_sum<RandomIt>, mid, end);
    int sum = parallel_sum(beg, mid);
    return sum + handle.get();
}
 
int main()
{
    std::vector<int> v(10000, 1);
    std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
 
    X x;
    // Calls (&x)->foo(42, "Hello") with default policy:
    // may print "Hello 42" concurrently or defer execution
    auto a1 = std::async(&X::foo, &x, 42, "Hello");
    // Calls x.bar("world!") with deferred policy
    // prints "world!" when a2.get() or a2.wait() is called
    auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");
    // Calls X()(43); with async policy
    // prints "43" concurrently
    auto a3 = std::async(std::launch::async, X(), 43);
    a2.wait();                     // prints "world!"
    std::cout << a3.get() << '\n'; // prints "53"
} // if a1 is not done at this point, destructor of a1 prints "Hello 42" here

 

참고 링크: https://www.modernescpp.com/index.php/tasks

 

Tasks - ModernesCpp.com

 

www.modernescpp.com

 

2020.12.15 - [programming/c++] - [c++] async

2020.12.15 - [programming/c++] - [c++] future

반응형

'💻 programming > c++' 카테고리의 다른 글

[c++] logger 클래스 만들기  (0) 2021.08.04
[c++] timer 클래스 만들기  (0) 2021.08.04
[c++] thread  (0) 2021.08.04
[c++] lvalue reference and rvalue reference  (0) 2021.08.04
[c++] condition variable (조건 변수)  (0) 2020.12.17

댓글