unique_lock的简单介绍
unique_lock类里维护了一个mutex对象。在unique_lock类拥有多个构造函数,这里只放两个本文涉及的构造函数。
explicit unique_lock(mutex_type& __m)
: _M_device(std::__addressof(__m)), _M_owns(false)
{
lock();
_M_owns = true;
}
该构造函数会直接对mutex对象加锁。
unique_lock(mutex_type& __m, defer_lock_t) noexcept
: _M_device(std::__addressof(__m)), _M_owns(false)
{ }
这个构造函数不进行加锁操作。其中第二个参数defer_lock_t是一个空类。
在unique_lock类的析构函数里,对mutex对象进行了解锁操作。
~unique_lock()
{
if (_M_owns)
unlock();
}
看完了unique_lock类的构造函数和析构函数就可以引出我想说明的两个小技巧了。
技巧一:
直接手动加解锁。直接看代码。
// unique_lock::lock/unlock
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock, std::defer_lock
std::mutex mtx; // mutex for critical section
void print_thread_id (int id) {
std::unique_lock<std::mutex> lck (mtx,std::defer_lock);
// critical section (exclusive access to std::cout signaled by locking lck):
lck.lock();
std::cout << "thread #" << id << '\n';
lck.unlock();
}
int main ()
{
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i)
threads[i] = std::thread(print_thread_id,i+1);
for (auto& th : threads) th.join();
return 0;
}
需要注意的是,这里要加std::defer_lock参数。这样会调用第二个构造函数,不对mutex进行加锁操作。后面由自己手动操作。好处是可以自己选择需要加解锁的代码段。
#include <iostream>
#include <thread>
int v = 1;
void critical_section(int change_v) {
static std::mutex mtx;
std::unique_lock<std::mutex> lock(mtx);
// do contention operations
v = change_v;
std::cout << v << std::endl;
// release the lock
lock.unlock();
// during this period,
// others are allowed to acquire v
// start another group of contention operations
// lock again
lock.lock();
v += 1;
std::cout << v << std::endl;
}
int main() {
std::thread t1(critical_section, 2), t2(critical_section, 3);
t1.join();
t2.join();
return 0;
}
也可以使用上面代码的方式确定加锁的位置。注意此时unique_lock构造时是加锁的。
技巧二:
这里做了一些改动,让unique_lock在构造时加锁,析构时解锁。为了确定需要加解锁的代码段,我们用{}花括号把代码段括起来。
// unique_lock::lock/unlock
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock, std::defer_lock
std::mutex mtx; // mutex for critical section
void print_thread_id (int id) {
// critical section (exclusive access to std::cout signaled by locking lck):
{
std::unique_lock<std::mutex> lck (mtx);
std::cout << "thread #" << id << '\n';
}
}
int main ()
{
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i)
threads[i] = std::thread(print_thread_id,i+1);
for (auto& th : threads) th.join();
return 0;
}
关注公众号《首飞》回复“机器人”获取精心推荐的C/C++,Python,Docker,Qt,ROS1/2等机器人行业常用技术资料。