링크를 참조하자, Thread, Async 간의 비교를 면밀히 해 두었다.
간략한 요약
1) std::async 역시 Thread 이다.
2) std::async 는 자동적으로 ThreadPool 에서 관리된다.
3) std::async 는 '값을 리턴' 받는데에 보다 중점이 맞춰져 있다.
4) std::thread 의 경우 동기점을 맞추고 블럭하는데에 .join() 이 쓰이고, 비동기로 운용하는데에 .detech() 가 쓰인다.
5) std::thread 의 경우엔 운영체제단과 직접적으로 연결되어 있기에, 생성, 삭제시에 비용이 다소 크다.
└ std::async 는 비교적 생성과 파괴에 있어서 비용이 적다. 즉 오버헤드를 줄일 수 있다.
6) std::async 를 함수 내에서 사용할 경우, 함수 밖의 메인 Thread 와 비동기적으로 운용할 수 없다.
└ C#의 async, await 같은 용도로 운용할 수 없다.
자세한 차이점 설명
6) 에 대해서 중점적으로 설명한다.
// header
class CallbackTimer
{
public:
CallbackTimer(int miliseconds, std::function<void()>& func);
};
// implement
CallbackTimer::CallbackTimer(int miliseconds, std::function<void()>& func)
{
auto result = std::async(std::launch::async,[miliseconds,func]()
{
std::this_thread::sleep_for(std::chrono::milliseconds(miliseconds));
func();
});
}
// main
void aaa(int a)
{
std::cout << "hello World!" << std::endl;
}
int main()
{
std::function<void()> func = std::bind(aaa, 10);
cyp::timer::CallbackTimer call(1000, func);
int temp;
std::cout << "123" << std::endl;
std::cin >> temp;
}
async 의 경우에는 std::futher 로 받지 않을경우 sequential 하게 진행이 이루워 진다.
때문에 반드시 값을 받아줘야 실질적인 thread 처럼 운용할 수 있다.
때문에 cppReference 내의 std::async 코드 설명 란에서도
모두 반환값을 받아 처리하는 모습을 볼 수 있다.
다시 위의 코드를 보자,
std::function<void()> 함수 포인터를 입력받아,
해당 함수 포인터 내에 존재하는 함수를 1초 뒤에 콜백 실행하는 코드이다.
실질적으로 함수 내부와, 함수 외부에서 일이 동시에 진행된다.
나는 위 코드에서 "123" 이 먼저 출력되고, "HELLO WORLD" 가 출력되는 상황을 원했지만 그러지 않았다.
이유는 result 변수 로 비록 값을 받았을 지언정,
함수 안과 밖이 sequencial 하게 운용되었기 때문인데,
함수 내부에서 이와 같이 async 를 이용할 경우, 결과값을 받아오기 전까지 함수를 빠져나갈 수 없기때문에
제아무리 std::launch::async 옵션을 통해 비동기적으로 운용하게 하려 해도
해당 함수를 빠져나갈 수 없게 막기 때문이다.
좀 더 직관적으로 살펴보면.
위 코드는 정상적으로 작동되지만,
위 코드는 에러를 내뿜는다.
thread 가 할당되어 있는 상태에서 메인 thread (프로세스) 의 종료 명령이 내려지기에 에러를 만들어 내는 것이다.
이를 무시하면서 비동기적으로 이용하기 위해서는
.detech() 를 이용해서 thread 가 어찌되던 무시하라는 명령을 내리면 된다.
당연히 thread 가 어찌되든 신경쓰지 않고, main Thread 는 완전히 따로 동작한다.
선언된 std::thread 가 main thread 에 의해 죽어도 '신경쓰지 마라' 고 명시했으므로, 오류 메세지를 출력하지 않는다.
하지만 std::async 는 좀 다르다.
std::async 는 .get(), wait() 을 만나게 되면, 반드시 해당 지점에서 '동기점을 맞춰 블럭시켜야 한다'
이와 동일하게 함수(메인함수를 포함한) 를 탈출할 때 역시 마찬가지이다.
해당 함수를 탈출할때에 async 내에 위치한 모든 작업을 완료 시킨뒤 결과값을 return 시켜야 한다.
때문에,
위와 같이 std::async 를 이용하면
이처럼 무조건적으로 결과값이 도출되기 전까지 '대기' 한다.
thread 로 따지면 무조건 join 하는것과 같다.
이것이 thread 와 async 의 사용에 있어서 유념해야 할 차이점이다.
async 의 경우 보다 안정적이고, 별 생각없이 사용할 수 있다는 장점이 있으나,
함수 내에서 thread 를 생성하여 비동기 논블럭 형식으로 운용하려면 std::async 가 아닌,
std::thread 를 사용해야 한다.
끝.
'Programming > C++' 카테고리의 다른 글
[C++] Char * vs Char [] (0) | 2021.11.25 |
---|---|
[C++] std::thread 를 멈추는 방법 (0) | 2021.09.18 |
[C++] 동적 라이브러리 vs 정적 라이브러리 개인 의견 (0) | 2021.08.22 |
[C++] 인터페이스에 관한 팁 (순수가상함수) (0) | 2021.06.09 |
[C++] 다형성 vitual 키워드에 관한 팁 (0) | 2021.06.09 |