1.WINDOWS临界区
同一个线程中,windows"相同临界区变量代表临界区"的进入
EnterCriticalSection(&my_winsec) 和LeaveCriticalSection(&my_winsec);成对出现;可以多次进入
同一线程,lock() 同一个互斥量多次,报异常
// 线程6.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>
#include<Windows.h>
#define _WINDOWSJQ
class A {
public:
//把收到的消息(玩家命令)写入到一个队列线程
void inMsgRecvQueue()
{
for (int i = 0; i<10000; i++)
{
cout << "inMesRecvQueue()执行,插入元素" << i << endl;
#ifdef _WINDOWSJQ
EnterCriticalSection(&my_winsec);//进入临界区
msgRecvQueue.push_back(i);
LeaveCriticalSection(&my_winsec);//离开临界区
#else
my_mutex1.lock();
msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队
my_mutex1.unlock();
#endif // _WINDOWSJQ
}
}
bool outMsgLULProc(int &command)
{
#ifdef _WINDOWSJQ
EnterCriticalSection(&my_winsec);
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
LeaveCriticalSection(&my_winsec);
return true;
}
LeaveCriticalSection(&my_winsec);
return false;
#else
my_mutex1.lock();
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
//这里是处理数据....
//cout << "处理数据" << command << endl;
my_mutex1.unlock();
return true;
}
my_mutex1.unlock();
return false;
#endif
}
//把数据从消息队列中取出的线程
void outMsgRecvQueue()
{
int command = 0;
for (int i = 0; i<10000; i++)
{
bool result = outMsgLULProc(command);
if (result)
cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
else
{
//消息队列为空
cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
}
}
cout << "消息队列处理完成" << endl;
}
A()
{
#ifdef _WINDOWSJQ
InitializeCriticalSection(&my_winsec);//初始化
#endif // _WINDOWSJQ
}
private:
list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
mutex my_mutex1;//创建互斥量
mutex my_mutex2;//创建互斥量
std::condition_variable my_cond;//生成一个条件变量对象
#ifdef _WINDOWSJQ
CRITICAL_SECTION my_winsec; //windows临界区
#endif // _WINDOWSJQ
};
int main()
{
A myobj;
thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用 避免复制
thread myOutMsgObj1(&A::outMsgRecvQueue, &myobj);
thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
myOutMsgObj.join();
myOutMsgObj1.join();
myInMsgObj.join();
cout << "主线程结束" << endl;
return 0;
}
2.自动析构技术
std::lock_guard
class CWinLock //叫RAII类 资源获取即初始化
// 线程6.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>
#include<Windows.h>
#define _WINDOWSJQ
//本类用于自动释放windows下的临界区,类似std::lock_gurad
class CWinLock //叫RAII类 资源获取即初始化
{
public:
CWinLock(CRITICAL_SECTION *pCritmp)
{
m_pCritical = pCritmp;
EnterCriticalSection(pCritmp);
}
~CWinLock()
{
LeaveCriticalSection(m_pCritical);
}
private:
CRITICAL_SECTION *m_pCritical;
};
class A {
public:
//把收到的消息(玩家命令)写入到一个队列线程
void inMsgRecvQueue()
{
for (int i = 0; i<10000; i++)
{
cout << "inMesRecvQueue()执行,插入元素" << i << endl;
#ifdef _WINDOWSJQ
//EnterCriticalSection(&my_winsec);//进入临界区
CWinLock as(&my_winsec);
CWinLock as1(&my_winsec); //多次进入,没问题
msgRecvQueue.push_back(i);
//LeaveCriticalSection(&my_winsec);//离开临界区
#else
//my_mutex1.lock();
std::lock_guard<std::mutex>obj1(my_mutex1);
std::chrono::microseconds timeout(100);
msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队
//my_mutex1.unlock();
#endif // _WINDOWSJQ
}
}
bool outMsgLULProc(int &command)
{
#ifdef _WINDOWSJQ
EnterCriticalSection(&my_winsec);
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
LeaveCriticalSection(&my_winsec);
return true;
}
LeaveCriticalSection(&my_winsec);
return false;
#else
my_mutex1.lock();
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
//这里是处理数据....
//cout << "处理数据" << command << endl;
my_mutex1.unlock();
return true;
}
my_mutex1.unlock();
return false;
#endif
}
//把数据从消息队列中取出的线程
void outMsgRecvQueue()
{
int command = 0;
for (int i = 0; i<10000; i++)
{
bool result = outMsgLULProc(command);
if (result)
cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
else
{
//消息队列为空
cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
}
}
cout << "消息队列处理完成" << endl;
}
A()
{
#ifdef _WINDOWSJQ
InitializeCriticalSection(&my_winsec);//初始化
#endif // _WINDOWSJQ
}
private:
list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
mutex my_mutex1;//创建互斥量
mutex my_mutex2;//创建互斥量
std::condition_variable my_cond;//生成一个条件变量对象
#ifdef _WINDOWSJQ
CRITICAL_SECTION my_winsec; //windows临界区
#endif // _WINDOWSJQ
};
int main()
{
A myobj;
thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用 避免复制
thread myOutMsgObj1(&A::outMsgRecvQueue, &myobj);
thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
myOutMsgObj.join();
myOutMsgObj1.join();
myInMsgObj.join();
cout << "主线程结束" << endl;
return 0;
}
- recursive_mutex 递归的独占互斥量,可以多次锁
std::mutex 独占互斥量,自己lock时,别人lock不了
recursive_mutex 递归的独占互斥量:允许同一个线程,同一个互斥量,多次被lock
recursive_mutex 有lock也有unlock
// 线程6.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>
#include<Windows.h>
//#define _WINDOWSJQ
//本类用于自动释放windows下的临界区,类似std::lock_gurad
class CWinLock //叫RAII类 资源获取即初始化
{
public:
CWinLock(CRITICAL_SECTION *pCritmp)
{
m_pCritical = pCritmp;
EnterCriticalSection(pCritmp);
}
~CWinLock()
{
LeaveCriticalSection(m_pCritical);
}
private:
CRITICAL_SECTION *m_pCritical;
};
class A {
public:
//把收到的消息(玩家命令)写入到一个队列线程
void inMsgRecvQueue()
{
for (int i = 0; i<10000; i++)
{
cout << "inMesRecvQueue()执行,插入元素" << i << endl;
#ifdef _WINDOWSJQ
//EnterCriticalSection(&my_winsec);//进入临界区
CWinLock as(&my_winsec);
CWinLock as1(&my_winsec); //多次进入,没问题
msgRecvQueue.push_back(i);
//LeaveCriticalSection(&my_winsec);//离开临界区
#else
//my_mutex1.lock();
std::lock_guard<std::recursive_mutex>obj1(my_mutex1);
testfuncl(); //加了三次锁
msgRecvQueue.push_back(i); //假设数字为接受的命令,直接进入消息队
//my_mutex1.unlock();
#endif // _WINDOWSJQ
}
}
bool outMsgLULProc(int &command)
{
#ifdef _WINDOWSJQ
EnterCriticalSection(&my_winsec);
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
LeaveCriticalSection(&my_winsec);
return true;
}
LeaveCriticalSection(&my_winsec);
return false;
#else
//my_mutex1.lock();
std::lock_guard<std::recursive_mutex>obj(my_mutex1);
/*std::chrono::milliseconds sleeptime(10000000);
std::this_thread::sleep_for(sleeptime);*/
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
//这里是处理数据....
//cout << "处理数据" << command << endl;
//my_mutex1.unlock();
return true;
}
//my_mutex1.unlock();
return false;
#endif
}
//把数据从消息队列中取出的线程
void outMsgRecvQueue()
{
int command = 0;
for (int i = 0; i<10000; i++)
{
bool result = outMsgLULProc(command);
if (result)
cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
else
{
//消息队列为空
cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
}
}
cout << "消息队列处理完成" << endl;
}
A()
{
#ifdef _WINDOWSJQ
InitializeCriticalSection(&my_winsec);//初始化
#endif // _WINDOWSJQ
}
void testfuncl()
{
std::lock_guard<std::recursive_mutex>obj1(my_mutex1);
testfuncl2();
}
void testfuncl2()
{
//std::lock_guard<std::recursive_mutex>obj1(my_mutex1);
std::lock_guard<std::recursive_mutex>obj1(my_mutex1);
}
private:
list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
std::recursive_mutex my_mutex1; //创建递归互斥量
#ifdef _WINDOWSJQ
CRITICAL_SECTION my_winsec; //windows临界区
#endif // _WINDOWSJQ
};
int main()
{
A myobj;
thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用 避免复制
thread myOutMsgObj1(&A::outMsgRecvQueue, &myobj);
thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
myOutMsgObj.join();
myOutMsgObj1.join();
myInMsgObj.join();
cout << "主线程结束" << endl;
return 0;
}
4.带超时功能的独占互斥量 std::timed_mutex
try_lock_for() 等待一段时间
try_lock_unit() 参数时一个未来的时间点
带超时功能的递归独占互斥量 std::recursive_timed_mutex 允许同一个线程多次获取这个互斥量
// 线程6.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<thread>
#include<iostream>
using namespace std;
#include<vector>
#include<list>
#include<mutex>
#include<Windows.h>
//#define _WINDOWSJQ
//本类用于自动释放windows下的临界区,类似std::lock_gurad
class CWinLock //叫RAII类 资源获取即初始化
{
public:
CWinLock(CRITICAL_SECTION *pCritmp)
{
m_pCritical = pCritmp;
EnterCriticalSection(pCritmp);
}
~CWinLock()
{
LeaveCriticalSection(m_pCritical);
}
private:
CRITICAL_SECTION *m_pCritical;
};
class A {
public:
//把收到的消息(玩家命令)写入到一个队列线程
void inMsgRecvQueue()
{
for (int i = 0; i<10000; i++)
{
cout << "inMesRecvQueue()执行,插入元素" << i << endl;
#ifdef _WINDOWSJQ
//EnterCriticalSection(&my_winsec);//进入临界区
CWinLock as(&my_winsec);
CWinLock as1(&my_winsec); //多次进入,没问题
msgRecvQueue.push_back(i);
//LeaveCriticalSection(&my_winsec);//离开临界区
#else
//my_mutex1.lock();
//std::lock_guard<std::recursive_mutex>obj1(my_mutex1);
//std::lock_guard<std::mutex>obj1(my_mutex1);
std::chrono::microseconds timeout(100);
//if (my_mutex1.try_lock_for(timeout)) //等待100ms 来尝试获取锁
if (my_mutex1.try_lock_until(std::chrono::steady_clock::now() + timeout))
{
msgRecvQueue.push_back(i);
my_mutex1.unlock();
}
else
{
std::chrono::microseconds sleeptime(100);
std::this_thread::sleep_for(sleeptime);
}
#endif // _WINDOWSJQ
}
}
bool outMsgLULProc(int &command)
{
#ifdef _WINDOWSJQ
EnterCriticalSection(&my_winsec);
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
LeaveCriticalSection(&my_winsec);
return true;
}
LeaveCriticalSection(&my_winsec);
return false;
#else
my_mutex1.lock();
//std::lock_guard<std::recursive_mutex>obj(my_mutex1);
//std::chrono::milliseconds sleeptime(10000);
//std::this_thread::sleep_for(sleeptime);
if (!msgRecvQueue.empty())
{
//消息不为空
command = msgRecvQueue.front();//返回第一个元素,但不检查元素是否存在
msgRecvQueue.pop_front();//移除第一个元素,但不返回
//这里是处理数据....
//cout << "处理数据" << command << endl;
my_mutex1.unlock();
return true;
}
my_mutex1.unlock();
return false;
#endif
}
//把数据从消息队列中取出的线程
void outMsgRecvQueue()
{
int command = 0;
for (int i = 0; i<10000; i++)
{
bool result = outMsgLULProc(command);
if (result)
cout << "outMsgRecvQueue()函数处理数据,去除一个元素 =" << command << endl;
else
{
//消息队列为空
cout << "outMsgRecvQueue()执行,但目前消息队列中为" << i << endl;
}
}
cout << "消息队列处理完成" << endl;
}
A()
{
#ifdef _WINDOWSJQ
InitializeCriticalSection(&my_winsec);//初始化
#endif // _WINDOWSJQ
}
private:
list<int> msgRecvQueue;//容器,专门用于代表玩家发送过来的消息
std::timed_mutex my_mutex1;//带超时功能的独占互斥量
#ifdef _WINDOWSJQ
CRITICAL_SECTION my_winsec; //windows临界区
#endif // _WINDOWSJQ
};
int main()
{
A myobj;
thread myOutMsgObj(&A::outMsgRecvQueue, &myobj);//第二个参数是引用 避免复制
thread myOutMsgObj1(&A::outMsgRecvQueue, &myobj);
thread myInMsgObj(&A::inMsgRecvQueue, &myobj);
myOutMsgObj.join();
myOutMsgObj1.join();
myInMsgObj.join();
cout << "主线程结束" << endl;
return 0;
}