Deadlock problem and solution + lock() function

//死锁,两个锁(两个互斥量),被两个线程按乱序使用导致死锁,跟解锁顺序无关
//死锁的解决办法一:保证两个互斥量上锁的顺序一致就不会死锁。
//解决方法二:std::lock()函数,一次锁住两个或两个以上的互斥量(至少两个,多了不限,1个不行);
//要么两个互斥量都锁住,要么两个互斥量都没锁住。如果只锁了一个,另外一个没锁成功,则它立即把已经锁住的互斥量解锁。

#include<iostream>
#include<thread>
#include<vector>//适合乱序取出数据
#include<list>//适合有序取出数据
#include<mutex>//互斥量

using namespace std;

class A {
    
    


public:
	void inMsgRecvQueue()
	{
    
    
		for (int i = 0; i < 10000; i++)
		{
    
    
			cout << "Insert a number in inMsgRecvQueue():" << i << endl;
			//死锁状态
			//my_mutex.lock();
			//函数处理数据
			///.....
			/// ......
			/// .......
			/// 开始处理第二个数据
			//my_mutex2.lock();
		
			//Guard 模式
			//lock_guard<mutex>msgRecGuard(my_mutex);
			//lock_guard<mutex>msgRecGuard2(my_mutex2);
			
			//解决方法二:lock()解决方法,配合unlock
			lock(my_mutex2, my_mutex);
			
				msgRecvQueue.push_back(i);
			
			
			//my_mutex.unlock();
			//my_mutex2.unlock();
			//方法二:不用unlock1的方法
			lock_guard<mutex>msgRecGuAdopt(my_mutex, adopt_lock);//adopt_lock不调用构造,自动析构,adopt_lock是个结构体对象,标记作用,可选择性构造lock
			lock_guard<mutex>msgRecGuAdopt2(my_mutex2, adopt_lock);
		}
	}
	
	
	 
	void outMsgRecvQueue()
	{
    
    
		int command = 0;
		for (int i = 0; i < 10000; i++)
		{
    
    
			//封装判断
			bool result = getTheNumber(command);
			if (result == true)
			{
    
    
				cout << "outMsg running, get the number:" << command ;
				//处理进行处理command数据
				//...
			}
			else {
    
    
				cout << "outMsg is running,but the list is empty!";
			}
			cout << endl;
			
		}
		
		
	}

private:
	list<int>msgRecvQueue;
	mutex my_mutex;//我的互斥量
	mutex my_mutex2;//测试死锁


protected:
	bool getTheNumber(int &command)//取command地址,所以修改了command的数据
	{
    
    
		//死锁状态
		/*my_mutex2.lock();
		my_mutex.lock();*/
		//解决方法一
		//lock_guard<mutex>getNum(my_mutex);
		//lock_guard<mutex>getNum(my_mutex2);

		my_mutex.lock();
		my_mutex2.lock();
		if (!msgRecvQueue.empty())
		{
    
    
			
			command = msgRecvQueue.front();//Return the first value of the msgRecvQueue,but front doesn't check data
			msgRecvQueue.pop_front();//Delete the first number of the msgRQ
			my_mutex2.unlock();
			my_mutex.unlock();
			return true;
		}
		my_mutex.unlock();
		my_mutex2.unlock();
		return false;
	}

};

int main() {
    
    
	A myobj;
	thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);
	thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
	

	if(myInMsgObj.joinable())
		myInMsgObj.join();
	else
		cout << "The myInMsg is joined!" << endl;
	if (myOutMsgObj.joinable())
		myOutMsgObj.join();
	else
		cout << "The myOutMsg is joined!" << endl;

}

Guess you like

Origin blog.csdn.net/guanxunmeng8928/article/details/107962492