06C++11多线程编程之lock_guard类模板

  • Post author:
  • Post category:其他




06C++11多线程编程之lock_guard类模板


1 lock_guard概念

  • 1)lock_guard是一个类模板,它是mutex的进化版,自动lock()和unlock。类似独占型智能指针unique_ptr,是一个保姆。在lock_guard生命周期结束自动释放锁,智能指针自动释放new出来的内存。
  • 2)使用lock_guard后不能再使用lock和unlock,否则会出现程序不稳定甚至崩溃。

    下面写一段lock_guard的伪代码:
#include <iostream>
#include <mutex>
using namespace std;

int main(){

	std::mutex mymutex;
	{
		std::lock_guard<mutex> lGuard(mymutex);//构造时自动上锁,出去花括号后lGuard生命周期结束,锁在析构自动释放,这就是lock_guard。
	}
	
	//接下来为非共享代码,因为上面已经被释放锁
	
	return 0;
}


2 lock_guard的共享代码案例


上一篇我们说到使用mutex的lock和unlock正确的保护了共享代码,下面我们将其替换为lock_guard。

#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

//准备用成员函数作为线程函数的方法写线程,成为消息处理类
class A{
public:
	//把收到的消息入到一个队列的线程
	void inMsgRecvQueue(){
		for (int i = 0; i < 10000; i++){
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;

			{
				lock_guard<mutex> lGuard(my_mutex);
				//my_mutex.lock();
				msgRecvQueue.push_back(i); //存放消息
				//my_mutex.unlock();
			}

		}
	}

	//将共享的代码放到一个函数处理,方便上锁解锁
	bool outMsgLULProc(int &command){
		lock_guard<mutex> lGuard(my_mutex);
		//my_mutex.lock();
		if (!msgRecvQueue.empty()){
			int command = msgRecvQueue.front();
			msgRecvQueue.pop_front();
			//my_mutex.unlock();  //所有分支都必须有unlock()
			return true;
		}
		//my_mutex.unlock();
		return false;
	}

	//把数据从消息队列取出的线程
	void outMsgRecvQueue(){
		int command = 0;
		for (int i = 0; i < 10000; i++){
			bool result = outMsgLULProc(command);
			if (result == true){
				cout << "outMsgRecvQueue()执行,取出一个元素" << endl;
				//处理数据
				//这里有可能也有需要共享的代码段
			}
			else{
				//消息队列为空
				cout << "inMsgRecvQueue()执行,但目前消息队列中为空!" << i << endl;
			}
		}
		cout << "end!" << endl;
	}

private:
	std::list<int> msgRecvQueue;//容器(消息队列),代表玩家发送过来的命令。
	std::mutex my_mutex;
};

int main(){
	A myobja;

	std::thread myOutMsgObj(&A::outMsgRecvQueue, &myobja);//第二个参数,地址,才能保证线程里用的是同一个对象
	std::thread myInMsgObj(&A::inMsgRecvQueue, &myobja);

	myOutMsgObj.join();
	myInMsgObj.join();

	cout << "主线程执行!" << endl;

	return 0;
}

结果可以看到是正常运行的。

在这里插入图片描述


3 lock_guard的参数2std::adopt_lock

  • 1)lock_guard的参数2只有一个std::adopt_lock。
  • 2)std::adopt_lock是个结构体对象,起一个标志作用,表示这个互斥量已经lock(),不需要在std::lock_guard构造里再次lock()。

代码案例看我的下一篇死锁文章,里面详细说了std::lock配合lock_guard的参数2解决死锁并且自动解锁的案例。



版权声明:本文为weixin_44517656原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。