본문 바로가기
프로그래밍

👨‍💻 [C++] C++ 에서 thread 의 join() 은 무엇이며, 어떻게 활용할 수 있나요?

by 밝음의기둥 2025. 1. 23.
반응형

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


👨‍💻 안녕하세요, 윌리 프로젝트의 윌리 입니다.

C++ 에서 thread 의 join() 은 무엇이며, 어떻게 활용할 수 있는지 간략히 알아보았습니다.


질문 >

C++ 에서 thread 의 join() 은 무엇이며, 어떻게 활용할 수 있나요?

답변 >

std::thread::join()란?

C++에서 std::thread::join()은 멀티스레드 동기화를 위한 함수로, 호출한 스레드가 대상 스레드가 종료될 때까지 기다리도록 하는 기능을 제공합니다. 스레드가 수행 중인 작업을 마칠 때까지 블록(block) 상태로 대기하여, 스레드 간의 작업 순서를 보장합니다.


std::thread::join()의 특징

  1. 동기화 보장:
    • join()을 호출한 스레드는 대상 스레드가 종료될 때까지 대기합니다.
    • 이로 인해, 스레드의 작업이 모두 완료된 후 다음 작업이 실행됩니다.
  2. 단일 호출 제한:
    • 한 스레드에 대해 join()은 단 한 번만 호출할 수 있습니다.
    • 두 번째 호출 시 std::system_error 예외가 발생합니다.
  3. 자원 해제:
    • join()은 스레드가 종료된 후에 시스템 자원을 해제합니다.
    • join() 없이 스레드 객체가 소멸되면, 프로그램은 비정상 종료됩니다.
  4. 비차단 호출 대비:
    • join()은 호출 스레드가 종료될 때까지 기다리므로, 비동기로 스레드가 동작하도록 하고 싶다면 detach()를 사용할 수 있습니다.

기본 사용법

1. 단일 스레드의 join() 사용

#include <iostream>
#include <thread>

void worker() {
    std::cout << "Worker thread is running." << std::endl;
}

int main() {
    std::thread t(worker); // 새로운 스레드 생성
    t.join();              // 메인 스레드는 worker 스레드가 종료될 때까지 대기
    std::cout << "Worker thread has finished." << std::endl;

    return 0;
}

출력 예시:

Worker thread is running.
Worker thread has finished.


활용 예제

2. 멀티스레드와 join()

#include <iostream>
#include <thread>

void worker(int id) {
    std::cout << "Thread " << id << " is starting." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Thread " << id << " has finished." << std::endl;
}

int main() {
    std::thread t1(worker, 1);
    std::thread t2(worker, 2);

    t1.join(); // t1 스레드 종료 대기
    t2.join(); // t2 스레드 종료 대기

    std::cout << "Both threads have finished." << std::endl;
    return 0;
}

출력 예시:

Thread 1 is starting.
Thread 2 is starting.
Thread 1 has finished.
Thread 2 has finished.
Both threads have finished.

3. 벡터를 사용한 다중 스레드 관리

#include <iostream>
#include <thread>
#include <vector>

void worker(int id) {
    std::cout << "Thread " << id << " is working." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Thread " << id << " is done." << std::endl;
}

int main() {
    const int numThreads = 3;
    std::vector<std::thread> threads;

    // 여러 스레드 생성
    for (int i = 0; i < numThreads; ++i) {
        threads.emplace_back(worker, i);
    }

    // 모든 스레드 join
    for (auto& t : threads) {
        t.join();
    }

    std::cout << "All threads are done." << std::endl;
    return 0;
}

출력 예시:

Thread 0 is working.
Thread 1 is working.
Thread 2 is working.
Thread 0 is done.
Thread 1 is done.
Thread 2 is done.
All threads are done.


join()와 detach()의 차이

특징  join()  detach()
동작 방식 호출 스레드가 종료될 때까지 대기 호출 스레드를 분리하여 백그라운드에서 실행
자원 해제 스레드 작업이 끝난 후 자원을 해제 스레드가 종료될 때 시스템이 자원을 자동 해제
사용 사례 스레드 종료를 기다려야 하는 작업 비동기로 실행되어도 되는 경우
제약 조건 스레드 종료를 보장 백그라운드 작업이 완료되지 않을 수 있음

주의사항

  1. join() 또는 detach() 호출 필수:
    • std::thread 객체가 소멸되기 전에 반드시 join()이나 detach()를 호출해야 합니다.
    • 그렇지 않으면 프로그램이 **std::terminate*를 호출합니다.
  2. 중복 호출 금지:
    • 한 스레드 객체에 대해 join()이나 detach()를 두 번 호출할 수 없습니다.
#include <iostream>
#include <thread>

void worker() {
    std::cout << "Worker thread is running." << std::endl;
}

int main() {
    std::thread t(worker);

    t.join();
    // t.join(); // 두 번째 호출 시 예외 발생 (std::system_error)

    return 0;
}

  1. 스레드 종료 후 호출:
    • 스레드가 이미 종료된 경우에도 join() 호출은 정상적으로 작동합니다.

결론

std::thread::join()은 멀티스레드 프로그래밍에서 스레드 동기화를 보장하며, 스레드가 작업을 완료하기 전에는 호출 스레드가 진행되지 않도록 설계되었습니다. 이는 스레드 간의 작업 순서를 보장하고 자원을 안전하게 관리하기 위해 필수적인 도구입니다.

  • 사용 사례:
    • 스레드 종료를 기다려야 하는 작업(예: 데이터 처리 완료 후 결과 출력).
    • 동기화가 필요한 멀티스레드 환경.
  • 대안:
    • 스레드가 백그라운드에서 비동기로 실행되길 원한다면 detach()를 사용할 수 있습니다.

join()은 스레드 관리와 동기화의 핵심이며, 이를 통해 안정적이고 효율적인 멀티스레드 프로그램을 작성할 수 있습니다.



🎬 유튜브 채널 🎬

 

위로그@WiLog

📢 안녕하세요, 위로그@WiLog 시청자 여러분, 저는 윌리(Willee) 입니다. 📢 위로그@WiLog 는 자기계발을 목적으로 하는 채널 입니다. 📢 오늘도 즐겁게~ 자신을 위한 계발을 함께 해보아요~ d^_^b 📌

www.youtube.com

🎬 치지직 채널 🎬

 

위로그 채널 - CHZZK

지금, 스트리밍이 시작됩니다. 치지직-

chzzk.naver.com


반응형