C++/STL

[C++] std::async, std::thread (2)

sseram 2023. 4. 10. 23:25
반응형

https://donot-simsim.tistory.com/35

 

[C++] std::async, std::thread (1)

둘 다 비동기 작업을 수행하기 위해 만드는 것은 동일. 다만 몇 가지의 차이는 있다. 쓰면서 가장 와닿았던 두 가지의 특성이 있는데, 1. std::thread는 그저 thread를 하나 만들 뿐이다. 그에 관한 관

donot-simsim.tistory.com

 

여기서 이어지는 두 번째.

 

2. std::thread는 해당 함수를 통해 값을 가져오는 건 좀 귀찮아서, 주로 watchdog 같은 곳에 사용하게 되더라.

반면 std::async는 만드는 순간 future object를 되돌려주기 때문에, 해당 함수에서 값을 얻어오는 대에 특화되어있다.

 

 

이번엔 두 번쨰.

 

 

async 는 thread와는 달리,만들 때 future object를 받는다.

그리고 그 future object를 통하여 값을 받아올 수 있다.

 


#include <future>
#include <iostream>

unsigned int func() {
	std::this_thread::sleep_for(std::chrono::seconds(2));
	return 3;
}


int main() {
	std::cout << "main start" << std::endl;

	std::future<unsigned int> t1 = std::async(func);

	std::cout << t1.get() << std::endl;
	std::cout << "main end" << std::endl;

	return 0;
}

 

이런 식으로.

 

 

이 함수를 수행하고 있으렴. 그럼 나중에 와서 값을 가져갈게~

이런 개념으로 사용하게 되었다.

 

그래서 실제로 사용을 해 보면

 

 

#include <future>
#include <iostream>

unsigned int func(int st, int ed) {
	int res = 0;
	for (int i = st; i < ed; i++) {
		res += i;
	}
	return res;
}


int main() {
	std::cout << "main start" << std::endl;

	std::future<unsigned int> t1 = std::async(func, 1, 50001);
	std::future<unsigned int> t2 = std::async(func, 50003, 88190);

	std::cout << t1.get() + t2.get() << std::endl;

	std::cout << "main end" << std::endl;

	return 0;
}

 

 

이런 식으로, 오래 걸리는 일을 시켜두고, 값만 가져간다는 느낌으로 사용하게 되었다.

 

 

반면, thread를 통해 위의 코드를 나타낸다고 하면..

 

#include <iostream>

std::atomic<unsigned int> res{ 0 };

void func(int st, int ed) {
	int res = 0;

	for (int i = st; i < ed; i++) {
		res += i;
	}

	::res += res;
}


int main() {
	std::chrono::high_resolution_clock clock;
	auto starttime = clock.now();


	std::cout << "main start" << std::endl;

	auto t1 = std::thread(func, 1, 50001);
	auto t2 = std::thread(func, 50003, 88190);

	std::this_thread::sleep_for(std::chrono::seconds(2));

	if (t1.joinable()) t1.join();
	if (t2.joinable()) t2.join();

	std::cout << ::res << std::endl;
    
	std::cout << "main end" << std::endl;

	return 0;
}

 

 

이런 느낌이 되려나...

여튼 return값이 없으니 굉장히 귀찮아진다. 애초에 이런 식으로 쓰기 위해 만든 놈이 아닌 듯 하다.

 

 

다만 watchdog처럼 계속 무언가의 상태를 보아야 한다면..

 

#include <future>
#include <iostream>

std::atomic<int> num{0};
std::atomic<bool> stopFlag{ false };

void func(int st, int ed) {
	while (stopFlag == false) {
		if (st < num && num < ed) {
			std::cout << "between!" << std::endl;
		}
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
}


int main() {
	std::cout << "main start" << std::endl;
	{
		std::thread(func, 1, 10).detach();
		auto a1 = std::async(func, 11, 20);
	}


	while (true) {
		int tmp;
		std::cin >> tmp;

		if (tmp == 0) {
			stopFlag = true;
			break;
		}

		num = tmp;
	}

	std::cout << "main end" << std::endl;

	return 0;
}

 

 

 

 

위의 코드가 있다.

 

func는 num이 특정 수 boundary 안에 들어오는지 확인하고, between을 출력한다.

 

 

	{
		std::thread(func, 1, 10).detach();
		auto a1 = std::async(func, 11, 20);
	}

 

 

이 부분은 {} 을 만들어서, 생성 / 소멸의 과정을 거치게끔 만든 것이다.

 

먼저 thread만 살리고 async를 주석해서 돌려보면

 

이런 식으로, 매우 잘 돈다.

 

생성자든 소멸자든, 이미 detach로 분리시켜 버렸기 때문에 알아서 돌다가, 끝날떄 flag만 제대로 넘겨주면 잘 종료된다.

 

 

하지만 thread를 주석처리 하고, async를 돌리면?

 

 

열심히 입력했었다.

 

 

 

죽는다.

 

 

future object가 소멸될 때, 관련된 함수가 끝날 때까지 기다렸다가 값을 받아가기 때문이라고 말한다.

위 코드에서는, {} 를 나갈 때 future가 소멸된다.

그러므로 a1은 실행시킨 func이 끝나기까지 기다리지만, 내부에서는 StopFlag를 기다리며 무한 루프를 돌게 되므로 위와 같은 상황이 벌어지게 된다.

 

 

c++ - Is there a way to cancel/detach a future in C++11? - Stack Overflow

 

 

Is there a way to cancel/detach a future in C++11?

I have the following code: #include <iostream> #include <future> #include <chrono> #include <thread> using namespace std; int sleep_10s() { this_thread::sleep_for(chr...

stackoverflow.com

 

 

 

위 부분을 class 내부에서 돌린다면... 해당 future object를 class member 변수로 가지고 있게 해서, 그 class가 소멸될 때까지 잘 관리를 해 주면 되겠지만, 굳이? 라는 생각이 더 크게 들더라.

 

thread는 만들고 그냥 detach 해 버리면 되는데...

 

 

그래서 결국

 

thread -> watchdog

async -> 오래 걸리는 일을 비동기적으로 작업해 return을 얻어올 때

 

 

이런 식으로 사용하게 되었다.

 

 

 

 

* 잘못된 정보는 알려주시면 너무너무 감사합니다.

반응형

'C++ > STL' 카테고리의 다른 글

[C++20] Concepts  (1) 2023.05.23
[C++] std::async. launch policy  (0) 2023.04.20
[C++] std::async, std::thread (1)  (0) 2023.04.09
[C++17] std::filesystem::path  (0) 2023.04.04
[C++17 ] FOLD Expression  (0) 2023.03.29