C++11中头文件 <mutex>
Mutex 类
std::mutex
最基本的 Mutex 类
构造函数,std::mutex不允许拷贝构造,最初产生的 mutex 对象是处于 unlocked 状态的。
lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
(1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁;
(2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住;
(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。unlock(), 解锁,释放对互斥量的所有权。
try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况:
(1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量;
(2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉;
(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
1 | std::mutex g_mutex; |
std::recursive_mutex
递归 Mutex 类,成员函数与std::mutex相同。
允许同一个线程对互斥量多次上锁(即递归上锁),来获得对互斥量对象的多层所有权,std::recursive_mutex 释放互斥量时需要调用与该锁层次深度相同次数的 unlock(),可理解为 lock() 次数和 unlock() 次数相同。
1 | std::recursive_mutex remutex; |
std::timed_mutex
定时 Mutex 类,比std::mutex多以下两个函数
try_lock_for() 函数接受一个时间范围,表示在这一段时间范围之内线程如果没有获得锁则被阻塞住。如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。
与 std::mutex 的 try_lock() 不同,try_lock 如果被调用时没有获得锁则直接返回 false。try_lock_until() 函数则接受一个时间点作为参数,在指定时间点未到来之前线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。
1 | std::timed_mutex mtx; |
std::recursive_timed_mutex
定时递归 Mutex 类, 成员函数与std::timed_mutex相同
Lock 类
std::lock_guard
与 Mutex RAII 相关,方便线程对互斥量上锁。 与Mutex配合使用,把锁放到lock_guard中时,mutex自动上锁,lock_guard析构时,同时把mutex解锁.
1 | std::mutex mMutex; |
std::unique_lock
与 Mutex RAII 相关,方便线程对互斥量上锁,提供了更好的上锁和解锁控制.
owns_lock(): 是否拥有锁
1
2_LIBCPP_INLINE_VISIBILITY
bool owns_lock() const _NOEXCEPT {return __owns_;}release(): 放弃对锁的关联,当析构时,不会unlock锁
1
2
3
4
5
6
7
8_LIBCPP_INLINE_VISIBILITY
mutex_type* release() _NOEXCEPT
{
mutex_type* __m = __m_;
__m_ = nullptr;
__owns_ = false;
return __m;
}
Tag 类
与Lock 类相关,通常作为参数传到Lock 类的构造函数里
std::adopt_lock_t
已经获得了锁
源码解析:std::lock_guard
1 | explicit lock_guard(mutex_type& __m) |
在构造函数中传入std::adopt_lock_t,会被认为已经获取到锁,不再进行获取锁的操作。
std::defer_lock_t
还没有获取到锁
std::try_to_lock_t
在Lock类构造时,尝试去获取锁