62 C++ 多线程 — mutex互斥量只能使用一次的问题分析—–以及解决方案递归mutex:recursive_mutex。

一 前提 以及问题

我们注意到,如果mutex.lock()两次,就会有问题
 

如下的代码有runtime exception

mutex mymutex;

mymutex.lock();

mymutex.lock();

//共享数据访问处理代码

mymutex.unlock();

mymutex.unlock();

但是有这样的case存在

class Teacher183 {
public:
	mutex mymutex;
	int num;
	int othernum;
	//1月份的时候,有个需求,我们写了个func1,共享数据num的访问,用mymutex保护
	void func1() {
		mymutex.lock();
		num++;
		mymutex.unlock();
	}

	//3月份的时候,公司有个新需求,我们写了个func1,共享数据othernum的访问,用mymutex保护
	void func2() {
		mymutex.lock();
		othernum++;
		mymutex.unlock();
	}


	//5月份的时候,公司有了一个新需求,这个需求,有一部分代码用到了func1和func2,那么我们按照习惯会这么写:

	void func3() {
		
		mymutex.lock();//func3 代码
		func1();
		// func3 代码
		func2();
		mymutex.unlock();//func3 代码
	}

};

void main() {
	Teacher183 tea;
	thread functhread1(&Teacher183::func1, &tea);
	thread functhread2(&Teacher183::func2, &tea);
	thread functhread3(&Teacher183::func3, &tea);
	functhread1.join();
	functhread2.join();
	functhread3.join();
}

二。recursive_mutex--可以多次lock()写在一起,多次unlock()写在一起

class Teacher183 {
public:
	recursive_mutex mymutex;
	int num;
	int othernum;
	//1月份的时候,有个需求,我们写了个func1,共享数据num的访问,用mymutex保护
	void func1() {
		mymutex.lock();
		num++;
		mymutex.unlock();
	}

	//3月份的时候,公司有个新需求,我们写了个func1,共享数据othernum的访问,用mymutex保护
	void func2() {
		mymutex.lock();
		othernum++;
		mymutex.unlock();
	}


	//5月份的时候,公司有了一个新需求,这个需求,有一部分代码用到了func1和func2,那么我们按照习惯会这么写:

	void func3() {
		
		mymutex.lock();//func3 代码
		func1();
		// func3 代码
		func2();
		mymutex.unlock();//func3 代码
	}

};

void main() {
	Teacher183 tea;
	thread functhread1(&Teacher183::func1, &tea);
	thread functhread2(&Teacher183::func2, &tea);
	thread functhread3(&Teacher183::func3, &tea);
	functhread1.join();
	functhread2.join();
	functhread3.join();
}