ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [씹어먹는 C++] 16 - 0 쓰레드 생성과 종료
    프로그래밍/C언어 2022. 2. 28. 22:00

    회사에서 파노라마 영상 생성하는 도중 속도 최적화를 위해 쓰레드를 적용해야 하는 경우가 생겼습니다. 이 일을 계기로 씹어먹는 c++이라는 책을 알게 되었고,  thread 공부한 것들을 정리해서 적어보겠습니다. 

     

     

    C++11 에서부터 표준에 쓰레드가 추가되면서 쓰레드 사용이 매우 편리해졌습니다.

    기본 코드는 다음과 같다. 

    #include <iostream>
    #include <thread>
    using std::thread;
    
    void f1() {
    	for (int i = 0; i < 10; i++) 
    		std::cout << "thread 1 running!\n" ;
    }
    
    void f2() {
    	for (int i = 0; i < 10; i++) 
    		std::cout << "thread 2 running! \n";	
    }
    
    void f3() {
    	for (int i = 0; i < 10; i++) 
    		std::cout << "thread 3 running! \n";	
    }
    
    int main() {
    	thread t1(f1);
    	thread t2(f2);
    	thread t3(f3);
    
    	t1.join();  // return the data from function in thread t1
    	t2.join();  // return the data from function in thread t2
    	t3.join();  // return the data from function in thread t3
    
    	// After join(), all the functions in thread is completed 
    	std::cout << "Done! -- 1 \n" ;
    }

    실행결과는 너무 길기 때문에 생략. 중요한 점은 마지막 "Done! --1\n"은모든 함수가 각각 10번씩 수행되고 마무리된 뒤에 출력된다. 그 이유는 .join() 함수 때문이다. 

    join 은, 해당하는 쓰레드들이 실행을 종료하면 리턴하는 함수이다. 따라서 t1.join()의 경우 t1이 종료하기 전까지 리턴하지 않는다. 그 말은 t2.join()이 실행되는 건 t1이 끝난 후인 것이다. t3.join()도 마찬가지. 만약 t1.join()을 thread t2(f2) 앞에 놓아버리면 직렬로 프로그램이 수행되는 거나 마찬가지므로 코드할 때 유의해야 한다. 

     

    만약 join을 하지 않으면 어떻게 될까?

    int main() {
      thread t1(f1);
      thread t2(f2);
      thread t3(f3);
        
      cout << "Done! --1\n";
    }

    그럼 Windows에서는 다음과 같이 성공적으로 프로그램이 종료되지 못한다. 

    그 이유는 쓰레드들의 내용이 모두 실행되기 전에 main 함수가 종료되면서 쓰레드 객체들 (t1, t2, t3)의 소멸자가 호출되었기 때문이다. C++ 표준에 따르면 join이나 detach되지 않은 쓰레드들의 소멸자가 호출되면 위처럼 예외를 발생시킨다.

    여기서 detach는 "해당 쓰레드를 실행시킨 후 잊어버리는 것"이라고 생각하면 된다. detach가 있다면 쓰레드는 알아서 백그라운드에서 돌아가게 된다.  다음 예제를 보자.

    int main() {
    	thread t1(f1);
    	thread t2(f2);
    	thread t3(f3);
    
    	t1.detach(); 
    	t2.detach();
    	t3.detach();
    
    	std::cout << "Done! -- 1 \n" ;
    }

    결과는 여러가지 형태로 나올 수 있는데 기본적으로 프로세스가 종료될 때 해당 프로세스 안에 있는 모든 쓰레드들은 종료 여부와 상관없이 자동으로 종료된다. 그래서 결국 메인함수가 종료되면 디버그 콘솔창에서 thread running! 을 출력할 수 없게 된다. 

    즉 detach()를 쓸 경우 main 함수에서 더이상 쓰레드가 종료될 떄까지 기다리지 않고, 종료하는 순간 thread 내용은 백그라운드로 돌아가게 된다. 

     

     

    쓰레드에 인자 전달하기

     

     

    댓글

Designed by Tistory.