참고한 것들
란?
- std::lock_guard 와 유사하게 scope 내에서만 lock 을 잡지만,
- 여기에다가 추가적인 기능까지 제공해주는 general purpose mutex 이다.
Lock tag
- Unique lock 에서는 lock 을 언제 잡는지를 설정해 줄 수 있다.
- 다음과 같은 것이 있다:
std::defer_lock: Unique lock 생성시에 lock 을 잡지 않음.std::try_to_lock: Unique lock 생성시에 lock 을 잡아 보고, 안되면 뭐 어쩔 수 없지std::adopt_lock: Lock 이 이미 잡혀있다고 가정하는 것이다.std::try_to_lock의 경우에는 unique lock 생성시에 lock 이 잡히지 않으면 해당 lock 의 lifecycle 은 unique lock 이 관리하지 않는다.- 즉, unique lock 이 소멸되어도 lock 이 풀리리라는 보장은 없다는 것.
- 하지만,
std::adopt_lock의 경우에는 unique lock 생성시에 lock 이 잡히지 않아도 lifecycle 은 unique lock 이 관리한다.- 즉, “관리주체 이전” 의 개념이라고 보면 되고, unique lock 이 소멸되면 lock 은 풀리게 된다.
코드 예시
#include <iostream>
#include <mutex>
int main() {
std::mutex m;
{
std::unique_lock<std::mutex> l(m);
std::cout << "[1] " << std::boolalpha << l.owns_lock() << std::endl;
}
{
std::unique_lock<std::mutex> dl(m, std::defer_lock);
std::cout << "[2] " << std::boolalpha << dl.owns_lock() << std::endl;
dl.lock();
std::cout << "[3] " << std::boolalpha << dl.owns_lock() << std::endl;
}
m.lock();
{
std::unique_lock<std::mutex> ttl(m, std::try_to_lock);
std::cout << "[4] " << std::boolalpha << ttl.owns_lock();
}
std::cout << " " << std::boolalpha << m.try_lock() << std::endl;
{
std::unique_lock<std::mutex> al(m, std::adopt_lock);
std::cout << "[5] " << std::boolalpha << al.owns_lock();
}
std::cout << " " << std::boolalpha << m.try_lock() << std::endl;
m.unlock();
}[1] true
[2] false
[3] true
[4] false false
[5] true true
- 위에서 말한 그대로이다:
[1]: Unique lock 은 기본적으로 생성시에 lock 을 잡는다.[2]:defer_lock모드일 때는 생성시에 lock 을 잡지 않는다.[3]:defer_lock모드를 사용할 때에는, 수동으로 lock 을 잡아야 한다.[4]:try_to_lock모드를 사용하면, 기존에 lock 이 걸린 경우 Unique lock 은 실패하고, lock cycle 을 unique lock 이 관리하지 않는다.- 따라서 첫
false는ttl이 lock 을 소유하고 있지 않다는 의미이고, - 두번째
false는ttl이 lock cycle 을 관리하지 않아 block 을 벗어난 다음에도 lock 이 풀리지 않아try_lock()이 실패하였다는 의미이다.
- 따라서 첫
[5]: 반면에adopt_lock모드의 경우에는 기존에 lock 이 걸려있었으면 lifecycle 을 가져온다.- 따라서 첫
true는 unique lock 이 해당 lock 을 소유하고 있다는 의미인 것이고, - 두번째
true는al이 소멸되자 lock 이 풀려 새로 lock 이 가능하다는 의미이다.
- 따라서 첫