(六)互斥量(mutex)

本文探讨了C++中互斥量的使用,强调了正确使用lock和unlock避免影响效率和保证数据安全的重要性。同时,解释了死锁的概念,指出互斥量上锁顺序不一致可能导致死锁,并提出了解决死锁的策略。通过示例代码展示了错误的锁顺序如何导致死锁情况。
摘要由CSDN通过智能技术生成

1、互斥量时一个类对象,形象的理解时一把锁,多个线程尝试用lock()成员函数加锁,只有一个线程可以锁成功,如果没有锁成功会不断的尝试去获取锁。

互斥量使用的时候要小心,多了影响效率,少了起不到全面的保护效果。

方法:调用lock unlock 必须成对出现

#include <thread>
#include <iostream>
#include <vector>
#include <list>
#include <Windows.h>
#include <mutex>
using namespace std;

class RecvQueue {
public:
	void inMsgRecvQueue() {
		for (int i = 0; i < 100000; ++i) {
			cout << "inMsgRecvQueue() start, push back one element: " << i << endl;
			my_mutex.lock();
			msgRecvQueue.push_back(i);
			my_mutex.unlock();
		}
	}
	bool outMsgLULProc(int &command) {
		my_mutex.lock();
		if (!msgRecvQueue.empty()) {
			command = msgRecvQueue.front();
			msgRecvQueue.pop_front();
			my_mutex.unlock();
			return true;
		}
		my_mutex.unlock();
		return false;
	}
	void outMsgRecvQueue() {
		for (int i = 0; i < 100000; ++i) {
			int command = 0;
			bool result = outMsgLULProc(command);
			if (result){
				cout << "outMsgRecvQueue is start, pop one element:" << command << endl;
			}
			else {
				cout << "outMsgRecvQueue is empty!" << endl;
			}
		}
	}

private:
	std::list<int> msgRecvQueue;
	mutex my_mutex;
};

void main() {
	RecvQueue myobj;
	thread myoutqueue(&RecvQueue::outMsgRecvQueue, &myobj);
	thread myinqueue(&RecvQueue::inMsgRecvQueue, &myobj);
	myoutqueue.join();
	myinqueue.join();
}

补充:

lock unlock可以两个函数可以通过lock_guard类模板直接取代。

2、死锁

产生条件:至少两个及以上的锁才有可能产生。

死锁的一般解决方案:

1)保证多个互斥量上锁的顺序一致就不会死锁

2)使用std::lock()函数模板,内部机制:如果互斥量中有一个没锁柱,会一直等待,等所有互斥量都锁住才会往下走,要么所有互斥量多锁住,要么都没锁,只有一个锁了会立即把已经锁的解锁。

注意:

使用模板也需要用unlock分别解锁每一个互斥量。

以下代码时产生死锁的代码:

#include <thread>
#include <iostream>
#include <vector>
#include <list>
#include <Windows.h>
#include <mutex>
using namespace std;

class RecvQueue {
public:
	void inMsgRecvQueue() {
		for (int i = 0; i < 100000; ++i) {
			cout << "inMsgRecvQueue() start, push back one element: " << i << endl;
			my_mutex1.lock();//读和写锁的顺序不一致产生死锁
			my_mutex2.lock();//读和写锁的顺序不一致产生死锁
			msgRecvQueue.push_back(i);
			my_mutex1.unlock();
			my_mutex2.unlock();
		}
	}
	bool outMsgLULProc(int &command) {
		my_mutex2.lock();//读和写锁的顺序不一致产生死锁
		my_mutex1.lock();//读和写锁的顺序不一致产生死锁
		if (!msgRecvQueue.empty()) {
			command = msgRecvQueue.front();
			msgRecvQueue.pop_front();
			my_mutex1.unlock();
			my_mutex2.unlock();
			return true;
		}
		my_mutex1.unlock();
		my_mutex2.unlock();
		return false;
	}
	void outMsgRecvQueue() {
		for (int i = 0; i < 100000; ++i) {
			int command = 0;
			bool result = outMsgLULProc(command);
			if (result){
				cout << "outMsgRecvQueue is start, pop one element:" << command << endl;
			}
			else {
				cout << "outMsgRecvQueue is empty!" << endl;
			}
		}
	}

private:
	std::list<int> msgRecvQueue;
	mutex my_mutex1;
	mutex my_mutex2;
};

void main() {
	RecvQueue myobj;
	thread myoutqueue(&RecvQueue::outMsgRecvQueue, &myobj);
	thread myinqueue(&RecvQueue::inMsgRecvQueue, &myobj);
	myoutqueue.join();
	myinqueue.join();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值