c++11并发与多线程

第五节 互斥量概念、用法、死锁演示及解决详解

(1)互斥量(mutex)的基本概念

(2)互斥量的用法

(2.1)lock(),unlock()
(2.2)std::lock_guard类模板

(3)死锁

(3.1)死锁演示
(3.2)死锁的一般解决方案
(3.3)std::lock()函数模板
(3.4)std::lock_guard的std::adopt_lock参数

第六节 unique_lock详解

(1)unique_lock取代lock_guard

unique_lock是一个类模板,工作中一般推荐使用lock_guard;lock_guard取代了mutex的lock()和unlock()
unique_lock比lock_guard灵活很多;效率上差一点,内存占用多一点。
std::lock_guard<std::mutex> sbguard1(my_mutex1, std::adopt_lock); // adopt_lock起一个标记作用

(2)unique_lock的第二个参数

(2.1)std::adopt_lock
	std::lock_guard<std::mutex> sbguard1(my_mutex1, std::adopt_lock); // adopt_lock起一个标记作用
	adopt_lock标记的效果就是“假设调用方”线程已经拥有了互斥的所有权(已经lock()成功了)。
	表示这个互斥量已经被lock了(你必须要把互斥量提前lock,否则回报异常),通知lock_guard不需要在构造函数中lock这个互斥量了;
	unique_lock的参数含义相同。
(2.2)std::try_to_lock
	我们会尝试用mutex的lock()去锁定这个mutex,但是如果没有锁定成功,也会立即返回,并不会阻塞;
	用这个的前提是自己不能先去lock(),否则会双重锁定。
(2.3)std::defer_lock
	用这个的前提是自己不能先去lock();
	defer_lock并没有给mutex加锁;初始化了一个没有加锁的mutex

(3)unique_lock的成员函数

(3.1)lock()
(3.2)unlock()
(3.3)try_lock()
(3.4)release()
	返回它所管理的mutex对象指针,并释放所有权;也就是说,这个unique_lock和mutex不再有联系。
	严格区分unlock()和release()
	sbguard1 = {_Pmtx=0x010ffd3c {...} _Owns=true }
	+		&my_mutex1	0x010ffd3c {...}	std::mutex *

(4)unique_lock所有权的传递

#include <iostream>
#include <thread>
#include <windows.h>
#include <string>
#include <vector>
#include <list>
#include <mutex>

using namespace std;

class A {
public:
	void inMsgRecvQueue()
	{
		for (int i = 0; i < 1000; ++i)
		{
			cout << "inMsgRecvQueue()执行,插入一个元素" << i << endl;

			{
				//6.1
				//std::lock_guard<std::mutex> sbguard(my_mutex1);
				//std::unique_lock<std::mutex> sbguard(my_mutex1);
				//6.2.1
				//my_mutex1.lock();		
				//std::unique_lock<std::mutex> sbguard1(my_mutex1, std::adopt_lock);
				//6.2.2
				/*std::unique_lock<std::mutex> sbguard1(my_mutex1, std::try_to_lock);
				if (sbguard1.owns_lock())
				{
					msgRecvQueue.push_back(i);
				}
				else
				{
					cout << "inMsgRecvQueue()执行,没拿到锁。" << endl;
				}*/
				//6.2.3
				//std::unique_lock<std::mutex> sbguard1(my_mutex1, std::defer_lock);	// 没有加锁的my_mutex1
				//sbguard1.lock();

				//6.3.3
				/*if (sbguard1.try_lock() == true)
				{
					msgRecvQueue.push_back(i);
				}
				else
				{
					cout << "inMsgRecvQueue()执行,没拿到锁。" << endl;
				}*/

				// 6.3.4
				std::unique_lock<std::mutex> sbguard1(my_mutex1);
				std::mutex *ptx = sbguard1.release();	// 
				msgRecvQueue.push_back(i);
				ptx->unlock();

				// 6.4
				std::unique_lock<std::mutex> sbguard1(my_mutex1);
				std::unique_lock<std::mutex> sbguard2(std::move(sbguard1));
				msgRecvQueue.push_back(i);
			}
		}	// end for
	}

	bool outMsgLULProc(int &command)
	{
		//std::lock_guard<std::mutex> sbguard(my_mutex1);
		//std::lock_guard<std::mutex> sbguard(my_mutex1);
		std::unique_lock<std::mutex> sbguard(my_mutex1);
		//my_mutex2.lock(); // 死锁
		//my_mutex1.lock();
		//my_mutex2.lock();
		std::chrono::milliseconds dura(10);
		std::this_thread::sleep_for(dura);
		//Sleep(20000);
		if (!msgRecvQueue.empty())
		{
			command = msgRecvQueue.front();
			msgRecvQueue.pop_front(); // 移除第一个元素
			//my_mutex1.unlock();
			//my_mutex2.unlock();
			return true;
		}
		//my_mutex2.unlock();
		//my_mutex1.unlock();
		return false;
	}

	void outMsgRecvQueue()
	{
		int command = 0;
		for (int i = 0; i < 1000; ++i)
		{
			bool result = outMsgLULProc(command);
			if (result == true)
			{
				cout << "outMsgRecvQueue()执行,移除第一个元素" << endl;
			}
			else
			{
				cout << "outMsgRecvQueue()执行,但目前消息队列中为空" << i << endl;
			}
		}
		cout << " end " << endl;
	}
private:
	std::list<int> msgRecvQueue;
	std::mutex my_mutex1;
	std::mutex my_mutex2;
};
int main()
{
	// 一、创建和等待多个线程
	//vector<thread> mythreads;
	//for (int i = 0; i < 10; ++i) 
	//{
	//	mythreads.push_back(std::thread(myPrint, i)); // 创建并开始执行
	//}

	//for (auto iter = mythreads.begin(); iter != mythreads.end(); ++iter)
	//{
	//	iter->join();
	//}

	// 数据共享问题分析
	// 有读有写

	// 三、共享数据的保护案例代码
	A myobja;
	std::thread myOutMsgObj(&A::outMsgRecvQueue, std::ref(myobja));
	std::thread myInMsgObj(&A::inMsgRecvQueue, std::ref(myobja));

	myOutMsgObj.join();
	myInMsgObj.join();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值