(1)windows臨界區
(2)多次進入臨界區實驗
(3)自動析構技術
(4)recursive_mutex遞歸的獨佔互斥量
(5)帶超時的互斥量std::timed_mutex和std::recursive_timed_mutex
#include <thread>
#include <windows.h>
#define __WINDOWS__
class A
{
public:
//把收到的消息放到一個隊列中
void inMsgRecvQueue() //unlock()
{
for(int i=0;i<10000;++i)
{
cout<<"inMsgRecvQueue():"<<i<<endl;
#ifdef __WINDOWS__
EnterCriticalSection(&my_winsec);//獲取鎖,進入臨界區
//Windows在同一個線程中,同一個臨界區變量,可以多次進入臨界區(兩次加鎖),但是需要(兩次解鎖)多次離開臨界區
EnterCriticalSection(&my_winsec);
msgRecvQueue.push_back(i);
LeavCriticalSection(&my_winsec);//解鎖,離開臨界區
LeavCriticalSection(&my_winsec);
#else
std::unique_lock<std::mutex> lguard1(my_mutex1); //linux中mutex是不可以lock兩次的
msgRecvQueue.push_back(i);//假設這個數字就是收到的命令,把他加入到隊列中
//代碼處理。。。
#endif
}
return ;
}
bool outMsgProc(int &command)
{ //雙重鎖定,雙重檢查
#ifdef __WINDOWS__
if(!msgRecvQueue.empty())
{ //添加這個雙重鎖定是因爲每次不管是不是空都加鎖然後再釋放效率低,這樣可以避免每次都加鎖
EnterCriticalSection(&my_winsec);//獲取鎖
if(!msgRecvQueue.empty())
{
command = msgRecvQueue.front();//返回第一個元素,但不檢查元素是否存在
msgRecvQueue.pop_front();//移除第一個元素
LeavCriticalSection(&my_winsec);//放開鎖
return true;
}
}
#else
if(!msgRecvQueue.empty())
{ //添加這個雙重鎖定是因爲每次不管是不是空都加鎖然後再釋放效率低,這樣可以避免每次都加鎖
std::unique_lock<std::mutex> lguard1(my_mutex1);
if(!msgRecvQueue.empty())
{
command = msgRecvQueue.front();//返回第一個元素,但不檢查元素是否存在
msgRecvQueue.pop_front();//移除第一個元素
return true;
}
}
#endif
return false;
}
//把數據從消息隊列中取出線程
void outMsgRecvQueue()
{
int command =0;
for(int i=0;i<10000;++i)
{
bool result=outMsgProc(command);
if(result==true)
{
cout<<"outMsgRecvQueue()執行,取出一個元素"<<command<<endl;
//對消息處理
}
else
{
//消息隊列爲空
sleep(100);
cout<<"outMsgRecvQueue()執行,但是消息隊列爲空"<<i<<endl;
}
}
cout<<"end"<<endl;
}
A()
{
#ifdef __WINDOWS__
InitializeCriticalSection(&my_winsec);//用臨界區之前需要初始化
#endif
}
private:
std::list<int> msgRecvQueue;//容器(消息隊列)專門用於代表玩家發送的命令
std::mutex my_mutex1;//創建了一個互斥量
std::mutex my_mutex2;//創建了一個互斥量
#ifdef __WINDOWS__
CRITICAL_SECTION my_winsec;//windows中的臨界區,類似linux中的mutex
#endif
};
int main()
{ //windows臨界區
//自動析構技術
A myobja;
std::thread my_out_Thread(&A::outMsgRecvQueue,&myobja);//outMsgRecvQueue爲起始函數的線程
std::thread my_in_Thread(&A::inMsgRecvQueue,&myobja);//inMsgRecvQueue爲起始函數的線程
outMsgRecvQueue.join();
inMsgRecvQueue.join();
cout<<"主線程收尾,正常退出"<endl;
return 0;
}