std::lock_guard的原理和应用
一、lock_guard
lock_guard是一种在作用域内控制可锁对象所有权的类型。
lock_guard具有两种构造方法:
- lock_guard(mutex& m)
- lock_guard(mutex& m, adopt_lock)
其中mutex& m是互斥量,参数adopt_lock表示假定调用线程已经获得互斥体所有权并对其进行管理了。。
二、使用示例
#include <iostream> #include <mutex> #include <vector> #include <string> #include <ctime> #include <thread> using namespace std; // 时间模拟消息 string mock_msg() { char buff[30] = { 0 }; static int i = 100000; sprintf_s(buff, "%d", i--); return buff; } class CMutexTest { public: void recv_msg(); //接收消息 void read_msg(); //处理消息 private: vector<string> msg_queue; //消息队列 mutex m_mutex; //互斥量 }; // 模拟接收消息 void CMutexTest::recv_msg() { while (true) { string msg = mock_msg(); cout << "recv the msg " << msg << endl; // 使用"{ }"限定lock_guard作用域 { lock_guard<mutex> mylockguard(m_mutex); // 消息添加到队列 msg_queue.push_back(msg); } this_thread::sleep_for(chrono::milliseconds(10));//方便观察数据 } } // 模拟读取处理 void CMutexTest::read_msg() { while (true) { // 已经加锁 m_mutex.lock(); // 传递所有权给lock_guard,并传入adopt_lock表示已获得所有权 lock_guard<mutex> mylockguard(m_mutex, adopt_lock); if (!msg_queue.empty()) { // 处理消息并移除 string msg = msg_queue.front(); cout << "read the msg " << msg << endl; msg_queue.erase(msg_queue.begin()); } this_thread::sleep_for(chrono::milliseconds(15));//方便观察数据 } } int main() { CMutexTest my_test; thread recv_thread(&CMutexTest::recv_msg, &my_test); //接收线程 thread read_thread(&CMutexTest::read_msg, &my_test); //处理线程 recv_thread.join(); read_thread.join(); }
三、原理分析
首先,从lock_guard<>可以看出它是一个模板类,它在自身作用域(生命周期)中具有构造时加锁,析构时解锁的功能。 从VS中查看代码,不难发现,其设计的思路简单而又巧妙:
template <class _Mutex> class lock_guard { // class with destructor that unlocks a mutex public: using mutex_type = _Mutex; //无adopt_lock参数,构造时加锁 explicit lock_guard(_Mutex& _Mtx) : _MyMutex(_Mtx) { // construct and lock _MyMutex.lock(); } //有adopt_lock参数,构造时不加锁 lock_guard(_Mutex& _Mtx, adopt_lock_t) : _MyMutex(_Mtx) { } // construct but dont lock //析构解锁 ~lock_guard() noexcept { _MyMutex.unlock(); } //屏蔽拷贝构造 lock_guard(const lock_guard&) = delete; lock_guard& operator=(const lock_guard&) = delete; private: _Mutex& _MyMutex; };
四、总结
std::lock_guard是非常巧妙的一种设计思路,利用类对象的生命周期,构造时使互斥量加锁,析构时使互斥量解锁,从而实现其作用域内对互斥量的管理。
上一篇:
通过多线程提高代码的执行效率例子