c++11多線程 windows臨界區、其他各種mutex互斥量 第十二講


(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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章