11.windows临界区,其他各种mutex互斥量

1.windows临界区

和c++11中的mutex非常类似

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
#include<windows.h>
using namespace std;


#define __WINDOWSJQ__	//一个开关,用windows编程 临界区取代mutex
class A {
public:
	A() {
#ifdef __WINDOWSJQ__
		InitializeCriticalSection(&my_winsec);//用临界区之前要初始化
#endif
	}
	void inMsg() {
		for (int i = 0; i < 10000; i++) {
			cout << "插入一个元素:" << i << endl;
#ifdef __WINDOWSJQ__
			EnterCriticalSection(&my_winsec);//进入临界区(加锁)
			myQueue.push(i);
			LeaveCriticalSection(&my_winsec);//离开临界区(解锁)
#else
			//lock unlock成对保护数据
			myMutex.lock();
			myQueue.push(i);
			myMutex.unlock();
#endif
		}
	}
	void outMsg() {
		for (int i = 0; i < 10000; i++) {
#ifdef __WINDOWSJQ__
			EnterCriticalSection(&my_winsec);//进入临界区(加锁)
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
			LeaveCriticalSection(&my_winsec);//离开临界区(解锁)
#else

			myMutex.lock();
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
			myMutex.unlock();
#endif
		}
	}
private:
	queue<int>myQueue;//消息队列
	mutex myMutex;//互斥量
#ifdef __WINDOWSJQ__
	CRITICAL_SECTION my_winsec;//windows中的临界区,非常类似于c++11中的mutex
#endif
};

int main() {
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话

	//输出正常
	return 0;

}


2.多次进入临界区试验

在同一线程中,windows中的“相同临界区变量”代表的临界区连续进入EnterCriticalSection可以多次,但是LeaveCriticalSection次数也要一样,而c++11 中mutex只能连续lock一次,unlock一次

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
#include<windows.h>
using namespace std;


#define __WINDOWSJQ__	//一个开关,用windows编程 临界区取代mutex
class A {
public:
	A() {
#ifdef __WINDOWSJQ__
		InitializeCriticalSection(&my_winsec);//用临界区之前要初始化
#endif
	}
	void inMsg() {
		for (int i = 0; i < 10000; i++) {
			cout << "插入一个元素:" << i << endl;
#ifdef __WINDOWSJQ__
			//连续enter两次
			EnterCriticalSection(&my_winsec);//进入临界区 lock
			EnterCriticalSection(&my_winsec);//进入临界区 lock
			myQueue.push(i);
			LeaveCriticalSection(&my_winsec);//离开临界区 unlock
			LeaveCriticalSection(&my_winsec);//离开临界区 unlock
#else
			//lock unlock成对保护数据
			myMutex.lock();
			myQueue.push(i);
			myMutex.unlock();
#endif
		}
	}
	void outMsg() {
		for (int i = 0; i < 10000; i++) {
#ifdef __WINDOWSJQ__
			EnterCriticalSection(&my_winsec);//进入临界区
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
			LeaveCriticalSection(&my_winsec);//离开临界区
#else

			myMutex.lock();
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
			myMutex.unlock();
#endif
		}
	}
private:
	queue<int>myQueue;//消息队列
	mutex myMutex;//互斥量
#ifdef __WINDOWSJQ__
	CRITICAL_SECTION my_winsec;//windows中的临界区,非常类似于c++11中的mutex
#endif
};

int main() {
	/*
	 
		在同一线程中,windows中的“相同临界区变量”代表的临界区连续进入EnterCriticalSection可以多次,但是LeaveCriticalSection次数也要一样
		而c++11 中mutex只能连续lock一次,unlock一次
	 */
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话

	//输出正常
	return 0;

}


3. 自动析构技术

RAII

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
#include<windows.h>
using namespace std;


#define __WINDOWSJQ__	//一个开关,用windows编程 临界区取代mutex

//本例用于自动释放windows下的临界区,防止忘记LeaveCriticalSection导致死锁情况的发生,类似于cpp11中的std::lock_guard<mutex>
class CWinLock {//RAII类,资源获取即初始化
public:
	CWinLock(CRITICAL_SECTION* pCritmp) {
		m_pCritical = pCritmp;
		EnterCriticalSection(m_pCritical);
	}
	~CWinLock() {
		LeaveCriticalSection(m_pCritical);
	}
private:
	CRITICAL_SECTION* m_pCritical;
};
class A {
public:
	A() {
#ifdef __WINDOWSJQ__
		InitializeCriticalSection(&my_winsec);//用临界区之前要初始化
#endif
	}
	void inMsg() {
		for (int i = 0; i < 10000; i++) {
			cout << "插入一个元素:" << i << endl;
#ifdef __WINDOWSJQ__
		
			CWinLock wlock(&my_winsec);		
			myQueue.push(i);
#else
			
			std::lock_guard<mutex>sbguard(myMutex);
			myQueue.push(i);
			
#endif
		}
	}
	void outMsg() {
		for (int i = 0; i < 10000; i++) {
#ifdef __WINDOWSJQ__
			CWinLock wlock(&my_winsec);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
#else

			std::lock_guard<mutex>sbguard(myMutex);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
		
#endif
		}
	}
private:
	queue<int>myQueue;//消息队列
	mutex myMutex;//互斥量
#ifdef __WINDOWSJQ__
	CRITICAL_SECTION my_winsec;//windows中的临界区,非常类似于c++11中的mutex
#endif
};


int main() {
	/*

		在同一线程中,windows中的“相同临界区变量”代表的临界区连续进入EnterCriticalSection可以多次,但是LeaveCriticalSection次数也要一样
		而c++11 中mutex只能连续lock一次,unlock一次
	 */
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话
	
	
	//输出正常
	return 0;

}



4.recursive_mutex递归的独占互斥量

问题提出:

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
#include<windows.h>
using namespace std;


//#define __WINDOWSJQ__	//一个开关,用windows编程 临界区取代mutex

//本例用于自动释放windows下的临界区,防止忘记LeaveCriticalSection导致死锁情况的发生,类似于cpp11中的std::lock_guard<mutex>
class CWinLock {//RAII类,资源获取即初始化
public:
	CWinLock(CRITICAL_SECTION* pCritmp) {
		m_pCritical = pCritmp;
		EnterCriticalSection(m_pCritical);
	}
	~CWinLock() {
		LeaveCriticalSection(m_pCritical);
	}
private:
	CRITICAL_SECTION* m_pCritical;
};
class A {
public:
	A() {
#ifdef __WINDOWSJQ__
		InitializeCriticalSection(&my_winsec);//用临界区之前要初始化
#endif
	}
	void testfunc1() {
		std::lock_guard<mutex>sbguard(myMutex);
		//干各种事
		testfunc2();//连续lock两次了
	}
	void testfunc2() {
		std::lock_guard<mutex>sbguard(myMutex);
		//干各种其他事

	}
	void inMsg() {
		for (int i = 0; i < 10000; i++) {
			cout << "插入一个元素:" << i << endl;
#ifdef __WINDOWSJQ__
		
			CWinLock wlock(&my_winsec);		
			myQueue.push(i);
#else
			
			std::lock_guard<mutex>sbguard(myMutex);
			testfunc1();//连续lock 3次了,肯定崩溃	!!!!!!!!!!!!
			myQueue.push(i);
			
#endif
		}
	}
	void outMsg() {
		for (int i = 0; i < 10000; i++) {
#ifdef __WINDOWSJQ__
			CWinLock wlock(&my_winsec);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
#else

			std::lock_guard<mutex>sbguard(myMutex);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
		
#endif
		}
	}
private:
	queue<int>myQueue;//消息队列
	mutex myMutex;//互斥量
#ifdef __WINDOWSJQ__
	CRITICAL_SECTION my_winsec;//windows中的临界区,非常类似于c++11中的mutex
#endif
};


int main() {
	/*

		在同一线程中,windows中的“相同临界区变量”代表的临界区连续进入EnterCriticalSection可以多次,但是LeaveCriticalSection次数也要一样
		而c++11 中mutex只能连续lock一次,unlock一次
	 */
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话
	
	
	//输出正常
	return 0;

}



解决:recursive_mutex
std::mutex独占互斥量,自己lock时别人lock不了
recursive_mutex : 递归的独占互斥量,允许同一个线程,同一个互斥量多次被连续lock()。使用它需要考虑代码是否有优化空间,效率上比mutex差。递归次数有限制。

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
#include<windows.h>
using namespace std;


//#define __WINDOWSJQ__	//一个开关,用windows编程 临界区取代mutex

//本例用于自动释放windows下的临界区,防止忘记LeaveCriticalSection导致死锁情况的发生,类似于cpp11中的std::lock_guard<mutex>
class CWinLock {//RAII类,资源获取即初始化
public:
	CWinLock(CRITICAL_SECTION* pCritmp) {
		m_pCritical = pCritmp;
		EnterCriticalSection(m_pCritical);
	}
	~CWinLock() {
		LeaveCriticalSection(m_pCritical);
	}
private:
	CRITICAL_SECTION* m_pCritical;
};
class A {
public:
	A() {
#ifdef __WINDOWSJQ__
		InitializeCriticalSection(&my_winsec);//用临界区之前要初始化
#endif
	}
	void testfunc1() {
		std::lock_guard<recursive_mutex>sbguard(myMutex);
		//干各种事
		testfunc2();//连续lock两次了
	}
	void testfunc2() {
		std::lock_guard<recursive_mutex>sbguard(myMutex);
		//干各种其他事

	}
	void inMsg() {
		for (int i = 0; i < 10000; i++) {
			cout << "插入一个元素:" << i << endl;
#ifdef __WINDOWSJQ__
		
			CWinLock wlock(&my_winsec);		
			myQueue.push(i);
#else
			
			std::lock_guard<recursive_mutex>sbguard(myMutex);
			testfunc1();//连续lock 3次了,不报异常了	!!!!!!!!!!!!
			myQueue.push(i);
			
#endif
		}
	}
	void outMsg() {
		for (int i = 0; i < 10000; i++) {
#ifdef __WINDOWSJQ__
			CWinLock wlock(&my_winsec);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
#else

			std::lock_guard<recursive_mutex>sbguard(myMutex);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
		
#endif
		}
	}
private:
	queue<int>myQueue;//消息队列
	//mutex myMutex;//互斥量
	std::recursive_mutex myMutex;//递归独占互斥量
#ifdef __WINDOWSJQ__
	CRITICAL_SECTION my_winsec;//windows中的临界区,非常类似于c++11中的mutex
#endif
};


int main() {
	/*

		在同一线程中,windows中的“相同临界区变量”代表的临界区连续进入EnterCriticalSection可以多次,但是LeaveCriticalSection次数也要一样
		而c++11 中mutex只能连续lock一次,unlock一次
	 */
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话
	
	
	//输出正常
	return 0;

}



5.带超时的互斥量std::timed_mutex和std:recursive_timed_mutex

5.1 time_mutex:带超时功能的独占互斥量

5.1.1 try_lock_for():

是等待一段时间,如果我拿到了,或者等待超过时间没拿到锁,就走下来

#include <iostream>
#include <thread>
#include<vector>
#include<string>
#include<queue>
#include<mutex>
#include<windows.h>
using namespace std;


//#define __WINDOWSJQ__	//一个开关,用windows编程 临界区取代mutex


class A {
public:
	A() {

	}

	void inMsg() {
		for (int i = 0; i < 10000; i++) {
			cout << "插入一个元素:" << i << endl;

			myMutex.lock();
			std::chrono::milliseconds timeout(10);
			if (myMutex.try_lock_for(timeout)) {//等待10毫秒来尝试获取锁
				myQueue.push(i);
				myMutex.unlock();
			}
			else {
				//没拿到锁
				cout << "没拿到锁,休息会" << endl;
				std::chrono::microseconds sleeptime(100);//休息100微妙
				std::this_thread::sleep_for(sleeptime);
				myMutex.unlock();
			}

		}
	}
	void outMsg() {
		for (int i = 0; i < 10000; i++) {

			//std::lock_guard<recursive_mutex>sbguard(myMutex);
			myMutex.lock();
			std::chrono::milliseconds timeout(20);
			std::this_thread::sleep_for(timeout);
			if (!myQueue.empty()) {
				int command = myQueue.front();
				myQueue.pop();

			}
			else {
				cout << "队列为空,i = " << i << endl;

			}
			myMutex.unlock();
		}
	}
private:
	queue<int>myQueue;//消息队列
	//mutex myMutex;//互斥量
	std::timed_mutex myMutex;//递归独占互斥量

};


int main() {
	/*

		在同一线程中,windows中的“相同临界区变量”代表的临界区连续进入EnterCriticalSection可以多次,但是LeaveCriticalSection次数也要一样
		而c++11 中mutex只能连续lock一次,unlock一次
	 */
	A myobj;
	thread outObj(&A::outMsg, &myobj);//第二个参数传入的是this指针 等价ref(myobj)
	thread inObj(&A::inMsg, &myobj);
	outObj.join();
	inObj.join();
	cout << "hello,world!" << endl;//最后执行这句话
	
	
	//输出正常
	return 0;

}



5.1.2 try_lock_unti():

参数一个未来的时间点,在未来时间没到的时间内,如果拿到了锁就走下来,没拿到也走下来
上面的代码改一句话就行:
在这里插入图片描述

5.2 std:recursive_timed_mutex: 带超时功能的递归独占互斥量

允许同一个线程连续多次获取互斥量
其他的差不多的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值