최신 C++ (C++11부터)에서는 멀티스레딩 작업을 위한 풍부한 도구가 존재합니다: std::thread, 뮤텍스 및 리소스 접근을 관리하기 위한 다양한 래퍼 객체. 스레드 간 안전한 상호작용은 다음 구성 요소를 이해해야 합니다:
경쟁 상태를 피하기 위해 가능할 때마다 RAII 래퍼를 사용하십시오. 동일한 뮤텍스를 반복적으로 획득하려고 하면 데드락이 발생합니다(재귀 뮤텍스가 아닌 경우).
올바른 작업 예:
#include <iostream> #include <mutex> #include <thread> std::mutex mtx; void printThreadSafe(int id) { std::lock_guard<std::mutex> lock(mtx); std::cout << "스레드 " << id << std::endl; } int main() { std::thread t1(printThreadSafe, 1); std::thread t2(printThreadSafe, 2); t1.join(); t2.join(); }
std::lock_guardstd::mutex를 사용하여 std::condition_variable로 조건 동기화를 구현할 수 있습니까?
답변: 아니요! std::condition_variable 작업을 위해서는 반드시 std::unique_lockstd::mutex가 필요합니다. lock_guard는 잠금을 제어할 수 있는 메서드를 제공하지 않기 때문에(예: 일시적으로 해제하고 다시 획득하는 unlock) 알림을 기다릴 때 필요합니다.
예:
std::mutex mtx; std::condition_variable cv; bool ready = false; void waitForEvent() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{return ready;}); // 추가 처리 }
이야기
프로젝트에서 수동으로 mtx.lock()/mtx.unlock()을 사용했습니다. lock/unlock 사이에 예외가 발생하면 뮤텍스가 잠긴 채로 남아 많은 스레드가 "멈춤" 상태가 되었습니다. RAII(
std::lock_guard)로 변경하니 문제는 사라졌습니다.
이야기
std::condition_variable을 통해 알림을 줄 때 std::unique_lock 대신 std::lock_guard를 사용했습니다. 결과적으로, 프로그램은 새로운 컴파일러에서 컴파일되지 않았고, 구 버전에서는 API 불일치로 인해 런타임 단언이 발생했습니다.
이야기
코드에서 std::lock_guard의 unlock()을 호출하여 뮤텍스 접근을 "수동적으로" 제어했습니다. 이는 다양한 컴파일러에서 정의되지 않은 동작으로 이어졌고, 때로는 애플리케이션이 중단되었습니다. lock_guard가 수동 해제를 지원하지 않음을 깨닫고 unique_lock으로 마이그레이션이 필요했습니다.