(十一)boost库之多线程间通信
生活随笔
收集整理的這篇文章主要介紹了
(十一)boost库之多线程间通信
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、互斥鎖
在編程中,引入了對象互斥鎖的概念,來保證共享數據操作的完整性。每個對象都對應于一個可稱為" 互斥鎖" 的標記,這個標記用來保證在任一時刻,只能有一個線程訪問該對象。
#include <iostream> #include <boost/thread.hpp> using namespace std; int g_num = 0; boost::mutex mu; //定義互斥鎖對象 int Func(int nCount) { for (int i = 0; i < nCount; i++) { boost::mutex::scoped_lock lock(mu); //對共享數據進行操作,需加鎖 g_num++; cout << __FUNCTION__ << ": " << g_num << endl; } return g_num; } int _tmain(int argc, _TCHAR* argv[]) { boost::thread th1(Func, 100); boost::thread th2(Func, 200); th1.join(); th2.join(); return 0; }2、讀寫鎖
boost::shared_mutex rw_mu; //定義讀寫鎖 int Write(int nCount) { for (int i = 0; i < nCount; i++) { boost::unique_lock<boost::shared_mutex> lock(rw_mu); //加唯一鎖 g_num++; cout << __FUNCTION__ << ": " << g_num << endl; } return g_num; } void Read(int nCount) { for (int i = 0; i < nCount; i++) { boost::shared_lock<boost::shared_mutex> lock(rw_mu); //加共享鎖 cout << __FUNCTION__ << ": " << g_num << endl; } } int _tmain(int argc, _TCHAR* argv[]) { boost::thread th1(Write, 100); boost::thread th2(Read, 100); boost::thread th3(Read, 100); th1.join(); th2.join(); th3.join(); return 0; }3、條件量
條件量相對于互斥鎖和讀寫鎖來說,并不是那么好理解,簡單點說,條件變量就是用于等待某個條件被觸發,但為什么要配合鎖使用呢,因為我們的等待不能是干等,那樣可能會出現死鎖。
如線程A負責添加任務到隊列,線程B負責處理隊列中的任務,隊列就是兩個線程的共享資源,使用前必須加鎖,但如果B線程加鎖后,發現隊列中沒有數據,然后等待,A線程準備添加任務時,發現
鎖已經被占用,于是就沒法添加任務,就形成了死鎖。但如果我等待時,釋放鎖資源,A線程就能正常添加任務,完成后通知B線程可以處理了,那么整個流程就暢通無阻了,這就是條件量的作用。
#include <queue> boost::mutex g_ioMutex; //輸出控制鎖 template<typename T> class CMsgQueue { public: CMsgQueue(size_t n):m_nCapacity(n) { } void Push(const T& val) { { boost::mutex::scoped_lock lock(m_mu); //加鎖 while(m_val.size() == m_nCapacity) //隊列已滿 { { boost::mutex::scoped_lock lock(g_ioMutex); cout << "隊列已滿" << endl; } m_condPush.wait(m_mu); //等待,將暫時的解鎖 } m_val.push(val); //添加數據到隊列 } m_condPop.notify_one(); //通知讀線程 } void Pop(T& val) { { boost::mutex::scoped_lock lock(m_mu); //加鎖 while(m_val.size() == 0) //隊列為空 { { boost::mutex::scoped_lock lock(g_ioMutex); cout << "隊列為空" << endl; } m_condPop.wait(m_mu); //等待可讀, } val = m_val.front(); //讀取數據 m_val.pop(); } m_condPush.notify_one(); //通知寫線程 } private: queue<T> m_val; //隊列 int m_nCapacity; //隊列最大容量 boost::condition_variable_any m_condPush; //寫入條件量 boost::condition_variable_any m_condPop; //讀取條件量 boost::mutex m_mu; //互斥鎖 }; CMsgQueue<int> g_numQueue(10); void FuncA(int nCount) { for (int i = 0; i < nCount; i++) { { boost::mutex::scoped_lock lock(g_ioMutex); cout << __FUNCTION__ << " Put " << i << endl; } g_numQueue.Push(i); } } void FuncB(int nCount) { for (int i = 0; i < nCount; i++) { int val; g_numQueue.Pop(val); boost::mutex::scoped_lock lock(g_ioMutex); cout << __FUNCTION__ << " Get " << val << endl; } } int _tmain(int argc, _TCHAR* argv[]) { boost::thread th1(FuncA, 50); boost::thread th2(FuncB, 20); boost::thread th3(FuncB, 30); th1.join(); th2.join(); th3.join(); return 0; }在多線程程序中,鎖的使用需要特別的小心,比如,我們將FuncA稍微改一下:
void FuncA(int nCount) { for (int i = 0; i < nCount; i++) { boost::mutex::scoped_lock lock(g_ioMutex); cout << __FUNCTION__ << " Put " << i << endl; g_numQueue.Push(i); } }如果改成這樣,程序將陷入死鎖,我們輕輕松松就制造了一個死鎖案例。
A線程占用了輸入鎖,那么B線程的Pop函數將一直在獲取輸入鎖的地方等待,但它已經占用了m_mu鎖,A線程也就只能一直在等待m_mu,故形成了死鎖。
總結
以上是生活随笔為你收集整理的(十一)boost库之多线程间通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (十)boost库之多线程
- 下一篇: (十二)boost库之多线程高级特性