icon안동민 개발노트

스레드 생성과 관리


스레드의 개념

 멀티스레딩은 현대 프로그래밍에서 중요한 개념입니다. C++ 11부터 표준 라이브러리에 스레드 지원이 추가되어, 운영체제에 독립적인 멀티스레드 프로그래밍이 가능해졌습니다.

 스레드는 프로그램 내에서 실행되는 독립적인 작업 단위입니다. 하나의 프로세스는 여러 개의 스레드를 가질 수 있으며, 이들은 같은 메모리 공간을 공유합니다. 멀티쓰레딩을 통해 여러 작업을 동시에 수행하여 프로그램의 성능을 향상시킬 수 있습니다.

std::thread 클래스

 C++ 11부터 <thread> 헤더에 정의된 std::thread 클래스를 사용하여 스레드를 생성하고 관리할 수 있습니다.

기본 사용법
// 기본 사용법
#include <iostream>
#include <thread>
 
void hello() {
    std::cout << "Hello from thread!" << std::endl;
}
 
int main() {
    std::thread t(hello);
    t.join();
    return 0;
}

 std::thread t(hello);는 새로운 스레드를 생성하고 hello 함수를 실행합니다. t.join();은 메인 스레드가 t 스레드가 완료될 때까지 기다리도록 합니다.

스레드에 인자 전달

 스레드 함수에 인자를 전달할 수 있습니다.

#include <iostream>
#include <thread>
#include <string>
 
void greet(const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
}
 
int main() {
    std::thread t(greet, "Alice");
    t.join();
    return 0;
}

람다 표현식으로 스레드 생성

 람다 표현식을 사용하여 스레드를 생성할 수 있습니다.

#include <iostream>
#include <thread>
 
int main() {
    auto lambda = [](int x, int y) {
        std::cout << "Sum: " << x + y << std::endl;
    };
 
    std::thread t(lambda, 10, 20);
    t.join();
    return 0;
}

스레드 ID

 각 스레드는 고유한 ID를 가집니다. get_id() 메서드를 사용하여 스레드 ID를 얻을 수 있습니다.

#include <iostream>
#include <thread>
 
void print_id() {
    std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;
}
 
int main() {
    std::thread t1(print_id);
    std::thread t2(print_id);
 
    t1.join();
    t2.join();
 
    return 0;
}

스레드 분리 (Detaching)

 detach() 메서드를 사용하여 스레드를 메인 스레드에서 분리할 수 있습니다.

#include <iostream>
#include <thread>
#include <chrono>
 
void background_task() {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "Background task completed!" << std::endl;
}
 
int main() {
    std::thread t(background_task);
    t.detach();
 
    std::cout << "Main thread continues..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));
 
    return 0;
}

 주의 : 분리된 스레드는 프로그램이 종료될 때 강제로 종료될 수 있으므로, 리소스 관리에 주의해야 합니다.

스레드 개수 제어

 std::thread::hardware_concurrency()를 사용하여 동시에 실행 가능한 스레드 수를 알 수 있습니다.

#include <iostream>
#include <thread>
 
int main() {
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << "Hardware concurrency: " << n << std::endl;
    return 0;
}

스레드 예외 처리

 스레드 내에서 발생한 예외는 해당 스레드 내에서 처리해야 합니다.

#include <iostream>
#include <thread>
#include <stdexcept>
 
void task_with_exception() {
    try {
        throw std::runtime_error("Error in thread");
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
}
 
int main() {
    std::thread t(task_with_exception);
    t.join();
    return 0;
}

연습 문제

  1. std::thread를 사용하여 1부터 100까지의 숫자 중 소수를 찾는 프로그램을 작성하세요. 여러 개의 스레드를 사용하여 작업을 분할하세요.
  2. 병렬 행렬 곱셈을 수행하는 프로그램을 작성하세요. 행렬의 각 행을 별도의 스레드에서 계산하도록 구현하세요.


참고 자료

  • C++ Concurrency in Action (2nd Edition) by Anthony Williams
  • Effective Modern C++ by Scott Meyers (Item 35-40)
  • C++ 표준 문서의 스레드 관련 섹션
  • CppCon 발표 영상들 - 동시성 프로그래밍 관련 세션들
  • Intel Threading Building Blocks (TBB) 문서