threads

김대익·2022년 3월 24일
0

std::thread는 class로 정의되어있으므로 쓰레드를 만드는 것은 객체를 만드는 것이다.
std::thread의 멤버 함수에는 constructor와 destructor, operator =가 있다.


먼저 constructor를 보면 std::thread를 만드는 4가지 정의가 있다
첫번째 정의는 thread생성시 인수를 넘겨주지않는 경우이다.
이 때는 main()함수 stack에 std::thread 객체는 만들지만
그 객체가 어떤 flow를 나타내지는 않는다.

만약 어떤 flow를 나타내는 thread가 필요하다면 인수에 함수를 넘겨주어야한다.

위에서 말한 두가지 이외에 copy, move constructor에 대한 내용이 있다.

copy constructor는 정의에서 삭제되어 컴파일에러가 발생하게되고

move constructor로 t1을 t2로 새로 정의할 때는 t1을 r-value로 바꾸는 과정이 필요하다.


destructor를 보면 객체를 삭제하는 destructor지만
thread가 joinable한 상태이면 std::terminate()를 실행시킨다.


join함수는 현재 thread를 block하고 target thread의 실행이 끝날때까지 기다린다
join이 없다면 destructor에서 말한 것처럼 thread보다 main()함수가 먼저 끝나버리고 thread객체가 남게된다


detach함수는 thread객체로부터 실행되는 thread를 분리시킨다

#include <iostream>
#include <thread>

void fn() {
	std::cout << "fn" << std::endl;
}

void threadCaller() {
	std::thread t1(fn);
    t1.detach();
}

int main() {
	threadCaller();
}

먼저 main()함수의 threadCaller()함수를 호출하면서 stack frame이 생기고 threadCaller() stack안에 thread 객체가 생성되고 이는 fn()을 실행하는 thread를 가리키게 된다.
이 상태에서 t1.detach();를 실행하면

thread 객체는 더이상 fn()을 실행하는 thread를 가리키지 않는다
그러므로 thread 객체가 해제가 되어도 fn()을 실행하는 thread는 해제되지않고 작업을 계속한다

실제 코딩시에는 detach보다는 global scope에 thread 객체를 만들고 해당 thread가 끝내기를 기다려주는 것이 좋다


#include <iostream>
#include <thread>

void fn() {
	int a = 0;
    std::cout << "fn" << std::endl;
}

int main() {
	std::cout << "press start" << std::endl;
    
    std::thread t1(fn);
    std::thread t2(fn);
    
    t1.join();
    t2.join();
    
    std::cout << "process end" << std::endl;
}

위 코드는 Thread객체 t1,t2를 만들어 함수 fn()을 넘겨주고 join함수를 통해 이 Thread들이 모두 종료되기를 기다리는 코드이다.

메모리 측면에서 보게되면
t1,t2는 각각의 stack시작지점을 가지고 local변수 a = 0;을 가진다

std::thread의 인수에는 이미 만들어진 함수뿐만 아니라 lambda함수도 사용이 가능하다.

std::thread t3([] {
	int a = 0;
    std::cout << "lambda thread" << std::endl;
});

0개의 댓글