Notice
Recent Posts
Recent Comments
NeuroWhAI의 잡블로그
[C++] lock tag(defer_lock, try_to_lock, adopt_lock) 설명 + scoped_lock 본문
개발 및 공부/언어
[C++] lock tag(defer_lock, try_to_lock, adopt_lock) 설명 + scoped_lock
NeuroWhAI 2018. 8. 26. 16:44mutex 헤더에 정의되어 있는 이 3개의 lock tag들은
mutex를 받는 표준 라이브러리 함수나 객체가 해당 mutex를 어떻게 취급할지 지정할 수 있게 해줍니다.
defer_lock : 뮤텍스를 잠그지 않습니다.
try_to_lock : 뮤텍스를 잠그려고 시도합니다. (이미 잠겨있다면 대기하지 않고 실패합니다)
adopt_lock : 이미 뮤텍스가 현재 스레드에 의해 잠겨있다고 가정합니다. (=잠그지 않습니다)
이걸 어디다 쓰느냐... 하실 수 있지만 생각해봅시다.
두 뮤텍스 a, b를 한번에 잠궈야할 일이 생긴다고 합시다.
이때 우리는 std::lock 함수를 사용해서 데드락 없이 둘 이상의 뮤텍스를 잠글 수 있으므로 아래와 같이 할 수 있을겁니다.
std::lock(a, b);
음... 잠그는건 성공했네요.
그럼 필요한 작업이 끝났으면 해제도 해야겠죠?
a.unlock();
b.unlock();
이렇게 하면 될까요?
물론 되기야 하겠지만 이 방식은 행여나 이전 작업 코드에서의 예외로 인해 unlock이 수행되지 않을 수 있는 상황이 발생할 수 있습니다.
그래서 우리가 unique_lock이나 lock_guard를 사용하는거죠?
아래와 같이 바꿔볼 수 있습니다.
std::lock(a, b);
std::lock_guard<std::mutex> lk1(a, std::adopt_lock);
std::lock_guard<std::mutex> lk2(b, std::adopt_lock);
자 adopt_lock이 쓰였네요.
adopt_lock은 이미 뮤텍스가 잠겨있다고 가정한다고 했습니다.
실제로 lock_guard를 생성하기 전 std::lock으로 잠군 상태입니다.
이치가 맞죠?
아래처럼 순서를 바꿔서도 할 수 있습니다.
std::lock_guard<std::mutex> lk1(a, std::defer_lock);
std::lock_guard<std::mutex> lk2(b, std::defer_lock);
std::lock(a, b);
defer_lock을 사용해서 뮤텍스를 바로 잠그지 않고 lock_guard를 생성한 뒤 lock 함수로 잠궜습니다.
상황에 따라 적절한 lock tag들을 사용하면 되겠습니다.
사실 C++17부터 지원하는 scoped_lock이란 녀석을 이용하면 위 3줄을 1줄로 줄일 수 있습니다.
std::scoped_lock lk(a, b);
위 과정을 자동으로 수행해주는 녀석이라고 보시면 됩니다.
scoped_lock도 lock tag를 지정할 수 있는데 adopt_lock만 지원한다는 것 참고하시면 되겠습니다.
그럼 즐프밍!
'개발 및 공부 > 언어' 카테고리의 다른 글
[C++] C++17의 Template argument deduction (템플릿 인자 추론) (0) | 2018.09.09 |
---|---|
[C++] Fold Expressions (0) | 2018.09.05 |
[Rust] in/exclusive range expression and pattern (0) | 2018.08.25 |
[C++] std::void_t를 이용해 클래스에 특정 멤버가 있는지 확인하기. (0) | 2018.08.05 |
[C++] 기본 인수(Default arguments) 고급 (0) | 2018.08.04 |
Comments