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:是待超時的遞歸獨占互斥量
智能推薦
Linux線程間同步 —— 互斥量(mutex)
1 互斥量簡介 互斥量是Linux線程間數據同步最主要和最常用的手段,能夠確保同一時間只有一個線程訪問數據。互斥量本質上就是一把鎖,當線程需要訪問數據時就啟用互斥量(加鎖),訪問完成后再釋放互斥量(解鎖)。對數據加鎖之后,其他線程不能訪問該數據,當然了也不能對該數據再次加鎖,這樣就保證任何時刻只有一個線程訪問共享數據。 如果線程嘗試對一個已經加鎖的數據再次加鎖,那么將會被阻塞,直到該數據解鎖為止。...
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 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...