반응형

std::unique_ptr 멀티스레드 환경 사용 시 주의사항

  • C++에서 std::unique_ptr는 동적 메모리의 소유권을 독점적으로 관리할 수 있도록 설계된 스마트 포인터입니다.
  • 그러나 이 포인터를 잘못 사용하면 멀티스레드(multi thread) 환경에서 치명적인 문제를 일으킬 수 있습니다.
  • 두 개 이상의 스레드가 동시에 하나의 std::unique_ptr에 접근하거나 조작하려고 하면 데이터 레이스(Data Race)와 예측 불가능한 동작(Undefined Behavior)이 발생할 수 있습니다.
  • 이번 글에서는 이러한 위험성과 올바른 사용법을 예제와 함께 정리합니다.


unique_ptr의 스레드 안전성

  • std::unique_ptr는 다음과 같은 특성을 가집니다.

      1. 소유권 독점: 한 번에 하나의 unique_ptr 객체만 자원을 소유합니다.
      1. 복사 불가능, 이동만 가능: 복사 연산은 금지되어 있으며, 이동(move) 연산으로만 소유권을 이전합니다.
      1. 내부 동기화 미제공: 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_ptrstd::mutex 조합을 고려하시기 바랍니다.



  • 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
  • 일부 모바일 환경에서는 ❤️ 버튼이 보이지 않습니다.

728x90
반응형

+ Recent posts