기존 함수를 thread로 실행시킬 수 있을까?🤔
목적 : 설계 때부터 thread 사용을 고려했다면 문제가 없었겠지만, 이미 구현까지 완료된 함수를 thread로 동작시켜야 할 때는 thread 함수를 사용하기 위한 기존 소스의 수정이 필요하다. 최대한 수정 없이 thread로 동작시킬 수 있는 방법은 없는지 알아보자.
Thread 함수 인자
std::thread의 생성자는 "가변인자 템플릿"으로 되어 있어 인자수를 원하는 만큼 늘릴 수 있으며,
thread로 실행시키기 위해서는 호출될 함수를 참조로 전달해야 하고 그 함수에 호출되는 인자를 다음인자로 넘기면 된다. 아래 f1, f2, f3를 thread로 실행하는 아래 예제를 참고해 보자.
#include <iostream>
#include <string>
#include <thread>
void f1() { }
void f2(int a, double d) { }
void f3(int a, int& b, std::string&& s) { b = 100;}
int main()
{
int n = 0;
std::string s = "hello";
//인자 전달 방법
std::thread t1(&f1); //인자없음
std::thread t2(&f2, 10, 3.4); //인자 2개 전달
//참조로 전달
std::thread t3(&f3, 10, std::ref(n), std::move(s) );
t1.join();
t2.join();
t3.join();
std::cout << s << std::endl; // ""
std::cout << n << std::endl; // 100
}
참고 : std::thread t1(&f1); 의 의미는 thread가 생성되는 동시에 f1를 thread로 실행시킨다.
f3 함수와 같이 참조로 인자를 전달하는 것도 가능하다.
std::move(x) 란?
move를 사용하면 이름대로 이동하진 않고 lvalue를 rvalue로 type casting만 한다. 예를 들어 move를 사용하지 않고 s를 인자로 전달 시, s 값이 복사가 되지만 move를 하면 메모리 할당은 발생하지 않고 메모리할당된 소유권이 t3으로 전달된다. (메모리 복사가 없음) 그래서 메모리 복사보다 빠르기에 성능을 향상시킬 수 있지만 move로 소유권이 넘어갔기에 주의하여 사용해야 한다. move 이후 s에 접근 시 에러가 발생한다. (하지만 로그 출력 시에는 null로 출력되는 것으로 확인할 수 있다.) 더 이상 s를 참조하지 않을 때 유용하다.
일반 함수뿐만 아니라 다양한 함수도 스레드로 수행할 수 있다.
일반함수뿐만 아니라 / 멤버함수/ 함수 객체 / 람다표현식 등 다양한 함수를 thread로 생성할 수 있다.
단 멤버 함수의 경우 "객체를 인자로 전달" 해야 한다. 아래 예제를 통해서 사용방법을 확인해 보자.
#include <iostream>
#include <thread>
struct Machine
{
void Run(int a, double d) {
std::cout << __func__ << " a : " << a << " d : " << d << "\n"<< std::endl;
}
};
struct Work
{
void operator()(int a, double b) const {
std::cout << __func__ << " a : " << a << " b : " << b << "\n"<< std::endl;
}
};
int main()
{
// 모든 종류의 callable object 를 스레드로 수행 가능
// 1. 멤버 함수
Machine m;
std::thread t1(&Machine::Run, &m, 1, 3.4);
// m.Run(1, 3.4) 를 스레드로
// 2. 함수객체
Work w; // 객체지만
w(1, 3.4); // 함수 처럼 사용가능
std::thread t2(w, 1, 3.4); // 주의 &w 가 아닌 w.
// 3. 람다 표현식을 스레드로 => 요즘 유행.
std::thread t3([](int a) {std::cout << "lambda\n"; }, 3);
t1.join();
t2.join();
t3.join();
}
참고
* 본 글에 예제 코드는 코드누리 교육을 받으면서 제공된 샘플코드를 활용하였습니다.
728x90
'L C++ > Concurrency' 카테고리의 다른 글
[Concurrency] 멀티(복수) 스레드를 보관하는 방법 (0) | 2023.08.15 |
---|---|
[Concurrency] 주요 기능 member type / class / functions 정리 (0) | 2023.08.01 |
[Concurrency] 좀비 스레드 생성될 수 있는가? (0) | 2023.07.18 |
[Concurrency] this_thread 특징 (0) | 2023.07.11 |
[Utilities] thread를 잘 사용하기 위한 std::reference_wrapper (std::ref) (활용 예시 추가) (0) | 2023.05.28 |