CodeNote
Coding Note
CodeNote
전체 방문자
오늘
어제
  • 전체 보기 (35)
    • C++ (33)
      • Modern C++ (12)
      • Modern C++ STL (0)
      • Thread (16)
      • Thread (Async) (5)
    • 디자인패턴 (0)
    • Algorithm (2)
    • Electron (0)
    • Python (0)

블로그 메뉴

  • 홈
  • Github
  • 태그
  • 방명록

공지사항

인기 글

태그

  • C++
  • LOCK
  • mutex
  • 자료구조
  • C++ #Memory
  • Free

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
CodeNote

Coding Note

[Thread] std::unique_lock
C++/Thread

[Thread] std::unique_lock

2022. 7. 17. 17:43

std::unique_lock

std::lock_guard와 비슷하지만 더 많은 기능을 가지고 있다.

 

Example Code

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>

struct MInt
{
    std::mutex mtx;
    int num = 0;
};

void plus1(MInt& mi)
{
    std::unique_lock<std::mutex> lck(mi.mtx);
    mi.num++;
}

int main()
{
    MInt mi;
    std::thread t1(plus1, std::ref(mi));
    std::thread t2(plus1, std::ref(mi));

    t1.join();
    t2.join();

    std::cout << "num : " << mi.num << std::endl;

    return 0;
}

std::lock_guard와 마찬가지로 unique_lock을 걸린 다음부터 크리티컬 섹션이 되고 스코프가 종료될 때 lock을 자동적으로 해제한다. 그렇다면 unique_lock은 왜 사용할까?라고 생각할텐데 unique_lock은 lock_guard보다 많은 기능을 가지고 있다.

 

cppreference에서 보면 lockguard는 constructor와 destructor만 정의되어있고, Copy와 Move또한 불가능한데 이는 매우 제한적인 용도로 사용될 수 있다라는 의미이다. 반면에 unique_lock은 그 밖에 여러 기능들을 포함하고 있다. 그 중에서 unique_lock의 가장 중요한 점은 Move가 가능하다는 것이다. 즉, unique_lock의 Move가 가능하다라는 뜻은 어떠한 함수의 파라미터로 보낼 수도 있고, return으로도 보낼 수 있다는 말이다.

 

Example Code

#include <iostream>
#include <thread>
#include <chrono>
#include <mutex>

struct MInt
{
    std::mutex mtx;
    int num = 0;
};

std::unique_lock<std::mutex> unlockTest(std::unique_lock<std::mutex> lck)
{
    // 어떠한 조건하에 lock을 해제한 후 return 할 수 있다.
    if (true)
    {
        lck.unlock();
    }
    return lck;
}

void plus1(MInt& mi)
{
    std::unique_lock<std::mutex> lck(mi.mtx);
    mi.num++;
    lck = unlockTest(std::move(lck)); // 오직 move만 가능하므로 RValue로 바꿔준다.
}

int main()
{
    MInt mi;
    std::thread t1(plus1, std::ref(mi));
    std::thread t2(plus1, std::ref(mi));

    t1.join();
    t2.join();

    std::cout << "num : " << mi.num << std::endl;

    return 0;
}

이러한 접근이 무엇이 특별하냐고 한다면 이는 개발자가 mutex lock을 리소스로 관리할 수 있게 만들어준다는 점이다. 쉽게 말해 스마트 포인터를 통해서 heap 메모리안에 생성된 오브젝트를 안전하게 관리할 수 있게 해준 것처럼 unique_lock을 사용하면 리소스 중에 하나인 mutex lock을 안전하게 관리할 수 있게 만들어준다.

 

그렇다면 언제 lock_guard를 사용하고 언제 unique_lock을 사용해야 하는가?

원칙은 언제나 lock_guard를 먼저 사용하고 unique_lock의 기능이 필요할 때 unique_lock을 사용하면 된다. 그 이유는 lock_guard는 unique_lock에 비해 (무시해도 될 정도지만) 더 가볍기도 하고 제한적인 기능만 가지고 있기 때문이다. 

'C++ > Thread' 카테고리의 다른 글

[Thread] std::shared_mutex  (0) 2022.07.17
[Thread] Deadlock, std::scoped_lock  (0) 2022.07.17
[Thread] std::mutex  (0) 2022.07.15
[Thread] Mutex(뮤텍스)  (0) 2022.07.15
[Thread] std::jthread (조이닝 쓰레드)  (0) 2022.07.13
    'C++/Thread' 카테고리의 다른 글
    • [Thread] std::shared_mutex
    • [Thread] Deadlock, std::scoped_lock
    • [Thread] std::mutex
    • [Thread] Mutex(뮤텍스)
    CodeNote
    CodeNote
    기록 블로그

    티스토리툴바