• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • C++11并發與多線程筆記(12) windows臨界區、其他各種mutex互斥量

    標簽: C++11并發與多線程  c++

    第十二節 windows臨界區、其他各種mutex互斥量

    在這里插入圖片描述

    一和二、windows臨界區
    Windows臨界區,同一個線程是可以重復進入的,但是進入的次數與離開的次數必須相等。
    C++互斥量則不允許同一個線程重復加鎖。

    windows臨界區是在windows編程中的內容,了解一下即可,效果幾乎可以等同于c++11的mutex
    包含#include <windows.h>
    windows中的臨界區同mutex一樣,可以保護一個代碼段。但windows的臨界區可以進入多次,離開多次,但是進入的次數與離開的次數必須相等,不會引起程序報異常出錯。

    #include <iostream>
    #include <thread>
    #include <list>
    #include <mutex>
    #include <Windows.h>
    
    #define __WINDOWSJQ_
    
    using namespace std;
    
    class A
    {
    public:
    	// 把收到的消息傳入隊列
    	void inMsgRecvQueue()
    	{
    		for (size_t i = 0; i < 1000; ++i)
    		{
    			cout << "收到消息,并放入隊列 " << i << endl;
    
    #ifdef  __WINDOWSJQ_
    			EnterCriticalSection(&my_winsec);	//	進入臨界區
    			//EnterCriticalSection(&my_winsec);	//	可以再次進入臨界區,程序不會出錯
    			msgRecvQueue.push_back(i);
    			LeaveCriticalSection(&my_winsec);	//	離開臨界區
    			//LeaveCriticalSection(&my_winsec);	//	如果進入兩次,必須離開兩次不會報錯
    #elif
    			my_mutex.lock();
    			msgRecvQueue.push_back(i);
    			my_mutex.unlock();
    #endif //  __WINDOWSJQ_
    		}
    
    		cout << "消息入隊結束" << endl;
    	}
    
    	// 從隊列中取出消息
    	void outMsgRecvQueue()
    	{
    		for (size_t i = 0; i < 1000; ++i)
    		{
    #ifdef  __WINDOWSJQ_
    			EnterCriticalSection(&my_winsec);	//	進入臨界區
    			if (!msgRecvQueue.empty())
    			{
    				// 隊列不為空
    				int num = msgRecvQueue.front();
    				cout << "從消息隊列中取出 " << num << endl;
    				msgRecvQueue.pop_front();
    			}
    			else
    			{
    				// 消息隊列為空
    				cout << "消息隊列為空 " << endl;
    			}
    			LeaveCriticalSection(&my_winsec);	//	離開臨界區
    #elif
    			my_mutex.lock();
    			if (!msgRecvQueue.empty())
    			{
    				// 隊列不為空
    				int num = msgRecvQueue.front();
    				cout << "從消息隊列中取出 " << num << endl;
    				msgRecvQueue.pop_front();
    				my_mutex.unlock();
    			}
    			else
    			{
    				// 消息隊列為空
    				cout << "消息隊列為空 " << endl;
    				my_mutex.unlock();
    			}
    #endif //  __WINDOWSJQ_
    		}
    
    		cout << "消息出隊結束" << endl;
    	}
    
    	A()
    	{
    #ifdef __WINDOWSJQ_
    		InitializeCriticalSection(&my_winsec);	//	用臨界區之前要初始化
    #endif // __WINDOWSJQ_
    
    	}
    
    private:
    	list<int> msgRecvQueue;
    	mutex my_mutex;
    
    #ifdef __WINDOWSJQ_
    	CRITICAL_SECTION my_winsec;	//	windows中的臨界區,非常類似C++11中的mutex
    #endif // __WINDOWSJQ_
    
    };
    
    int main()
    {
    	A myobj;
    	thread	myInMsgObj(&A::inMsgRecvQueue, &myobj);
    	thread	myOutMsgObj(&A::outMsgRecvQueue, &myobj);
    	myInMsgObj.join();
    	myOutMsgObj.join();
    
    	getchar();
    	return 0;
    }
    

    三、自動析構技術
    C++:lock_guard防止忘了釋放信號量,自動釋放
    windows:可以寫個類自動釋放臨界區:

    class CWinLock {
    public:
        CWinLock(CRITICAL_SECTION *pCritmp)
        {
            my_winsec =pCritmp;
            EnterCriticalSection(my_winsec);
        }
        ~CWinLock()
        {
            LeaveCriticalSection(my_winsec)
        };
    private:
        CRITICAL_SECTION *my_winsec;
    };
    

    上述這種類RAII類(Resource Acquisition is initialization),即資源獲取及初始化。容器,智能指針屬于這種類。

    四、遞歸獨占互斥量 std::recursive_mutex
    std::mutex 獨占式互斥量

    std::recursive_mutex:允許在同一個線程中同一個互斥量多次被 lock() ,(但是遞歸加鎖的次數是有限制的,太多可能會報異常),效率要比mutex低。

    如果你真的用了 recursive_mutex 要考慮代碼是否有優化空間,如果能調用一次 lock()就不要調用多次。

    五、帶超時的互斥量 std::timed_mutex 和 std::recursive_timed_mutex

    5.1 std::timed_mutex:是待超時的獨占互斥量

    • try_lock_for():

    等待一段時間,如果拿到了鎖,或者超時了未拿到鎖,就繼續執行(有選擇執行)如下:

    std::chrono::milliseconds timeout(100);
    if (my_mymutex.try_lock_for(timeout)){
        //......拿到鎖返回ture
    }
    else{
        std::chrono::milliseconds sleeptime(100);
        std::this_thread::sleep_for(sleeptime);
    }
    
    • try_lock_until():

    參數是一個未來的時間點,在這個未來的時間沒到的時間內,如果拿到了鎖頭,流程就走下來,如果時間到了沒拿到鎖,流程也可以走下來。

    std::chrono::milliseconds timeout(100);
    if (my_mymutex.try_lock_until(chrono::steady_clock::now() + timeout)){
        //......拿到鎖返回ture
    }
    else{
        std::chrono::milliseconds sleeptime(100);
        std::this_thread::sleep_for(sleeptime);
    }
    

    兩者的區別就是一個參數是時間段,一個參數是時間點

    5.2 std::recursive_timed_mutex:是待超時的遞歸獨占互斥量

    版權聲明:本文為qq_38231713原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_38231713/article/details/106093490

    智能推薦

    Linux線程間同步 —— 互斥量(mutex)

    1 互斥量簡介 互斥量是Linux線程間數據同步最主要和最常用的手段,能夠確保同一時間只有一個線程訪問數據。互斥量本質上就是一把鎖,當線程需要訪問數據時就啟用互斥量(加鎖),訪問完成后再釋放互斥量(解鎖)。對數據加鎖之后,其他線程不能訪問該數據,當然了也不能對該數據再次加鎖,這樣就保證任何時刻只有一個線程訪問共享數據。 如果線程嘗試對一個已經加鎖的數據再次加鎖,那么將會被阻塞,直到該數據解鎖為止。...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    精品国产乱码久久久久久蜜桃不卡