반응형
C++
에서std::unique_ptr
는 동적 메모리의 소유권을 독점적으로 관리할 수 있도록 설계된 스마트 포인터입니다.- 그러나 이 포인터를 잘못 사용하면 멀티스레드(
multi thread
) 환경에서 치명적인 문제를 일으킬 수 있습니다. - 두 개 이상의 스레드가 동시에 하나의
std::unique_ptr
에 접근하거나 조작하려고 하면 데이터 레이스(Data Race
)와 예측 불가능한 동작(Undefined Behavior
)이 발생할 수 있습니다. - 이번 글에서는 이러한 위험성과 올바른 사용법을 예제와 함께 정리합니다.
-
std::unique_ptr
는 다음과 같은 특성을 가집니다.-
- 소유권 독점: 한 번에 하나의
unique_ptr
객체만 자원을 소유합니다.
- 소유권 독점: 한 번에 하나의
-
- 복사 불가능, 이동만 가능: 복사 연산은 금지되어 있으며, 이동(
move
) 연산으로만 소유권을 이전합니다.
- 복사 불가능, 이동만 가능: 복사 연산은 금지되어 있으며, 이동(
-
- 내부 동기화 미제공:
unique_ptr
객체에 대한 멀티스레드 동시 접근 시 스레드 안전성을 보장하지 않습니다.
- 내부 동기화 미제공:
-
-
따라서 두 개의 스레드에서 하나의
std::unique_ptr
인스턴스를 동시에 참조하거나 조작하면 정의되지 않은 동작이 발생합니다.
-
cpp
#include <iostream> #include <memory> #include <thread> void threadFunc(std::unique_ptr<int>& ptr) { if (ptr) { std::cout << "쓰레드에서 값: " << *ptr << std::endl; } } int main() { std::unique_ptr<int> uptr = std::make_unique<int>(42); std::thread t1(threadFunc, std::ref(uptr)); std::thread t2(threadFunc, std::ref(uptr)); t1.join(); t2.join(); return 0; }
- 두 스레드가 동시에
uptr
에 접근합니다. unique_ptr
내부는 동기화되지 않으므로 데이터 레이스 및 정의되지 않은 동작이 발생할 수 있습니다.- 프로그램이 크래시하거나 이상한 출력이 발생할 가능성이 높습니다.
-
cpp
#include <iostream> #include <memory> #include <thread> void threadFunc(std::unique_ptr<int> ptr) { if (ptr) { std::cout << "쓰레드에서 값: " << *ptr << std::endl; } } int main() { std::unique_ptr<int> uptr = std::make_unique<int>(42); std::thread t1(threadFunc, std::move(uptr)); t1.join(); if (!uptr) { std::cout << "메인 스레드: uptr은 이제 nullptr" << std::endl; } return 0; }
std::move
를 통해 소유권을 안전하게 스레드에 전달합니다.- 이동 후 원래 unique_ptr은
nullptr
이 되므로 더 이상 접근하지 않습니다.
std::unique_ptr
는 절대 두 개의 스레드에서 동시에 접근하면 안 됩니다.- 멀티스레드 환경에서 리소스를 전달하려면
std::move
를 통해 소유권을 안전하게 넘기세요. - 여러 스레드에서 동시에 같은 리소스를 사용해야 할 때는
std::shared_ptr
와std::mutex
조합을 고려하시기 바랍니다.
- 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
- 일부 모바일 환경에서는 ❤️ 버튼이 보이지 않습니다.
728x90
반응형
'C C++' 카테고리의 다른 글
C++ 스마트 포인터(std::unique_ptr, std::shared_ptr, std::weak_ptr) 명시적 해제(reset()) (0) | 2025.03.20 |
---|---|
C++17에서 std::auto_ptr가 제거된 이유 (0) | 2025.03.20 |
C++11 std::move 개념과 활용 — 이동 시멘틱의 올바른 이해 (0) | 2025.03.19 |
GCC 버전별 주요 C++20 기능 지원 현황 (0) | 2025.03.19 |
C++ 표준 컨테이너 std::vector와 std::list의 차이점 비교 (0) | 2025.03.19 |