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: 带超时功能的递归独占互斥量
允许同一个线程连续多次获取互斥量
其他的差不多的