unique_lock
std::unique_lock比std::lock_guard更灵活,这种灵活性主要体现在以下几点:
- lock_guard在构造时或者构造前(std::adopt_lock)就已经获取互斥锁,并且在作用域内保持获取锁的状态,直到作用域结束;而unique_lock在构造时或者构造后(std::defer_lock)获取锁,在作用域范围内可以手动获取锁和释放锁,作用域结束时如果已经获取锁则自动释放锁。
- lock_guard锁的持有只能在lock_guard对象的作用域范围内,作用域范围之外锁被释放,而unique_lock对象支持移动操作,可以将unique_lock对象通过函数返回值返回,这样锁就转移到外部unique_lock对象中,延长锁的持有时间。
int n;
std::mutex some_mutex;
void prepare_data()
{
cout << n++ << endl;
}
void do_something()
{
cout << n++ << endl;
}
std::unique_lock<std::mutex> get_lock()
{
std::unique_lock<std::mutex> lk(some_mutex);
cout << "owns_lock? " << lk.owns_lock() << endl;
prepare_data();
return lk;
}
int main()
{
std::mutex mutex2;
std::unique_lock<std::mutex> lock2(mutex2, std::defer_lock);
cout << "owns_lock? " << lock2.owns_lock() << endl;
lock2.lock();
std::cout << "owns_lock? " << lock2.owns_lock() << endl;
lock2.unlock();
cout << "owns_lock? " << lock2.owns_lock() << endl;
std::unique_lock<std::mutex> lk(get_lock());
do_something();
}
由于unique_lock对象需要根据当前对象是否已经持有锁还是未持有进行判断从而执行适当的操作,因此比lock_guard占用空间稍大一点,效率稍低一点,std::unique_lock.owns_lock返回当前是否持有锁。 通常来说不应该在持有锁的期间执行消耗时间长的操作,此时unique_lock更加灵活,可以随时unlock,避免不相关的操作期间仍然持有锁。
std::unique_lock<std::mutex> my_lock(the_mutex);
some_class data_to_process = get_next_data_chunk();
my_lock.unlock();
result_type result = process(data_to_process);
my_lock.lock();
write_result(data_to_process, result);
|