콘텐츠로 이동

C++20 jthread와 stop_token — 협력적 스레드 취소

C++20은 std::thread의 두 가지 문제를 해결한 std::jthread를 도입했습니다.

  1. 자동 join: 소멸자에서 자동으로 join()을 호출합니다.
  2. 협력적 취소: std::stop_token으로 스레드에 취소 요청을 보낼 수 있습니다.

#include <thread>
#include <chrono>
#include <iostream>
void task() {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "완료\n";
}
int main() {
std::jthread t(task);
// 소멸자에서 자동 join — join() 호출 불필요
}

#include <thread>
#include <chrono>
#include <iostream>
void worker(std::stop_token st) {
while (!st.stop_requested()) {
std::cout << "작업 중...\n";
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
std::cout << "취소 요청 수신, 종료\n";
}
int main() {
std::jthread t(worker);
std::this_thread::sleep_for(std::chrono::seconds(1));
t.request_stop(); // 취소 요청 전송
// 소멸자에서 자동 join
}

3. stop_callback — 취소 시 정리 작업

섹션 제목: “3. stop_callback — 취소 시 정리 작업”
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable_any cv;
void worker(std::stop_token st) {
// 취소 요청 시 condition_variable을 깨움
std::stop_callback cb(st, [&] { cv.notify_all(); });
std::unique_lock lock(mtx);
cv.wait(lock, st, [] { return false; }); // stop_token 인식 대기
std::cout << "대기 해제\n";
}
int main() {
std::jthread t(worker);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
t.request_stop();
}

#include <thread>
#include <vector>
#include <iostream>
int main() {
std::stop_source src;
std::vector<std::jthread> workers;
for (int i = 0; i < 4; ++i) {
workers.emplace_back([i](std::stop_token st) {
while (!st.stop_requested()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << "워커 " << i << " 종료\n";
}, src.get_token()); // 공유 토큰 전달
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
src.request_stop(); // 모든 워커에 취소 요청
}

항목std::threadstd::jthread
소멸자 동작std::terminate() 호출자동 join()
취소 지원없음stop_token
join 필요필수불필요
사용 가능 버전C++11C++20

6. 실전 패턴: 백그라운드 서비스

섹션 제목: “6. 실전 패턴: 백그라운드 서비스”
class BackgroundService {
std::jthread thread_;
void run(std::stop_token st) {
while (!st.stop_requested()) {
process();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void process() { /* 실제 작업 */ }
public:
void start() {
thread_ = std::jthread([this](std::stop_token st) { run(st); });
}
void stop() { thread_.request_stop(); }
};

std::jthread는 RAII 기반 자동 join과 협력적 취소를 제공해 스레드 생명주기 관리를 크게 단순화합니다. 새 코드에서는 std::thread 대신 std::jthread를 기본으로 사용하세요.