C++11多线程unique_lock与lock_guard

lock_guard:

  • 一个互斥量包装程序,提供了一种RAII风格的机制来再作用域块的持续时间内拥有一个互斥量;
  • 创建该对象时,它会去获取提供给它的互斥锁的所有权,当控制流离开该对象作用域时,lock_guard析构并释放互斥量。
  • lock_guard本身并没有提供加锁和解锁的接口(实际存在需求,只能保证在析构的时候释放锁。
  • 不能复制。

unique_lock:

  • 也是一个互斥量的包装程序;
  • 允许延迟锁定,显示深度锁定,递归锁定,锁定所有权转移,和条件变量一起使用;
  • 提供了lock()和 unlock()接口,在析构的时候,会根据当前状态来决定是否要进行解锁。
  • 不能复制,但能移动。

使用lock_guard就需要创建两个局部对象来管理同一个互斥锁。

 1 class LogFile {
 2     std::mutex _mu;
 3     ofstream f;
 4 public:
 5     LogFile() {
 6         f.open("log.txt");
 7     }
 8     ~LogFile() {
 9         f.close();
10     }
11     void shared_print(string msg, int id) {
12         {
13             std::lock_guard<std::mutex> guard(_mu);
14             //do something 1
15         }
16         //do something 2
17         {
18             std::lock_guard<std::mutex> guard(_mu);
19             // do something 3
20             f << msg << id << endl;
21             cout << msg << id << endl;
22         }
23     }
24 
25 };

如下面代码显示,unique_lock可以灵活控制上锁和释放,这样避免重复的实例化lock_guard对象,还能减少锁的区域。(可以使用std::defer_lock设置初始化的时候不进行默认的上锁操作)

 1 void shared_print(string msg, int id) {
 2     std::unique_lock<std::mutex> guard(_mu, std::defer_lock);
 3     //do something 1
 4 
 5     guard.lock();
 6     // do something protected
 7     guard.unlock(); //临时解锁
 8 
 9     //do something 2
10 
11     guard.lock(); //继续上锁
12     // do something 3
13     f << msg << id << endl;
14     cout << msg << id << endl;
15     // 结束时析构guard会临时解锁
16 }

C++11中的unique_lock使用起来要比lock_guard更灵活,但是效率会低,内存的占用也会大。unique_lock也是一个类模板,但是比起lock_guard,它通过自己的成员函数来更加灵活进行锁的操作。

posted @ 2022-05-03 23:27  Siu_Miner  阅读(246)  评论(0)    收藏  举报