프로그래밍 지식/C++

C++문법 / Thread, 스레드 - 생성, join, detach

게임이 더 좋아 2021. 12. 2. 22:14
반응형
728x170

 

이전에는 WIN API를 이용해야 했지만

C++ 11 에서부터 표준에 쓰레드가 추가되어서 우리는 그저 잘 사용해서 먹으면 된다.

 

그래서 thread 헤더를 이용해서 기본적인 실행을 해봤다.

#include <iostream>
#include <thread>

using namespace std;

void func1() {
    for (int i = 0; i < 10; i++) {
        cout << "first running for " << i <<"\n";
    }
}

void func2() {
    for (int j = 0; j < 10; j++) {
        cout << "second running for " << j << "\n";
    }
}

void func3() {
    for (int k = 0; k < 10; k++) {
        cout << "third running for " << k << "\n";
    }
}
int main() {
    thread t1(func1); //스레드 객체 t1을 생성 후 해당 스레드로 func1 실행
    thread t2(func2);
    thread t3(func3);

    t1.join(); //해당하는 쓰레드들이 실행을 종료하면 리턴하는 함수
    //없으면 main함수가 먼저 종료되어서 thread가 소멸해버림
    //thread 작업이 끝날 떄까지 main함수가 끝나지 않게하는 방법
    t2.join();
    t3.join();
}

 

 

중요한 부분은

우선 thread를 생성하고 이용하는 방법

thread t1(func1);

스레드 객체 t1을 생성 후 해당 스레드로 func1 실행

 

그리고 thread의 작업이 끝날 때까지 반환하거나 소멸하지 않게 하는 법

t1.join();

해당하는 쓰레드들이 실행을 종료하면 리턴하는 함수
없으면 main함수가 먼저 종료되어서 thread가 소멸해버림
thread 작업이 끝날 떄까지 main함수가 끝나지 않게하는 방법

 

 

하지만 위 코드를 실행하면 개판난다.

cout이라는 것이 한 줄로 썼다고 하나가 아니라 여러 개라서 그렇다.

( <<할 때마다 cout이 한 번 더 실행된다고 생각하면 된다 )

 

일부

 

그렇다면 cout << 을 하나만 하게 바꿔보자.

이런식으로

cout << "first running \n";

잘나온다!!

 

그리고 할 때마다 결과가 다른데..?

그것은 OS가 스케줄링을 매번 다르게 하기 때문이다.

걱정안해도 된다.

OS는 사용자가 최적으로 사용하게끔 관리한다.

 

 


 

또한 thread 마다 stack은 따로 할당되기 때문에

func() 안의 for문에서도 3개다 i로 고쳐도 된다.

 

다 i로 똑같으면 어떡해???

thread1의 i는 4라면 thread2 가 작업할 떄 영향을 끼치진 않을까??

아니다. 

 

해당 함수에 필요한 변수들을 stack에 따로 저장되어 사용되고 공유하지 않는다.

void func1() {
  for (int i = 0; i < 10; i++) {
    cout << "first running \n";
  }
}

void func2() {
  for (int i = 0; i < 10; i++) {
    ...
  }
}

void func3() {
  for (int i = 0; i < 10; i++) {
    ...
  }
}

 

 


 

그렇다면 detach는 무엇일까?

Attach의 반대다.

떨어뜨려놓는 것이다.

즉, 해당 메인 스레드에서 분리하여 백그라운드로 보내는 것이다.

우리는 메인에서 스레드가 종료되는 시점에 자원을 반환받는 것이 보장되지만 - > join()

 

백그라운드에서는 해당 스레드가 언제 종료될 지를 모른다. -> detach()

 

한 번 사용해보자

 

...
    t1.detach();
    t2.detach();
    t3.detach();
    
    cout << "main has been terminated \n";
    
}

 

결과는..?

 

???뭐야??

하지만 프로세스 자체가 종료되면

해당 프로세스 안에 있는 모든 스레드들은 종료 여부와 상관없이 자동으로 종료된다.

그렇기 때문에 메인 함수가 종료됨을 알리고 프로세스가 종료하게 되면

detach를 했더라도 func1, func2, func3 는 백그라운드에서 동작할 수 없다.

 

??그럼 몇개 나온 것은 뭔데..?

다행히 메인함수가 완전히 종료되기 전에 스레드가 몇가지 실행하다가 끝난 것이다.

 


스레드의 기본적인 동작을 알아봤다.

 

스레드 생성

스레드 반환

스레드 종료 조건

스레드 분리

 

다음 글에서 응용해보자

728x90
반응형
그리드형