boost--线程同步
?1、互斥鎖(互斥量)
? mutex是獨占式的互斥鎖。timed_mutex增加了超時功能。
? 成員函數:lock()用于鎖定,try_lock()為非阻塞版本的鎖定,unlock()用于解鎖。timed_lock()只屬于timed_mutex,它可以等待一定的時間,等待的時間可以是一個時間段,也可以是指定的時間。
??使用方法:使用mutex必須配合try-catch塊以保證解鎖互斥量,eg:
#include "boost\thread.hpp"int main() {boost::mutex mu;try{mu.lock();cout << "Need to be protected" << endl; //io流是個共享資源,多線程內使用的話需要同步 mu.unlock();}catch (...){mu.unlock();}return 0; } View Code? mutex還提供了一系列的RAII型的互斥鎖,用于取消麻煩的try-catch塊,它會在構造的時候鎖定互斥量,析構時自動解鎖,eg:
#include "boost\thread.hpp"int main() {boost::mutex mu;boost::mutex::scoped_lock lock(mu);cout << "Need to be protected" << endl; //io流是個共享資源,多線程內使用的話需要同步return 0; } View Code? 使用實例:以下定義了一個支持原子前++的計數器atom_increase:
#include "boost\thread.hpp"template<typename T> class atom_increase { public:atom_increase(T x = 0): n(x){} //轉換構造函數,實現T類型到atom_increase類型的隱式轉換 T operator++() //重載前++運算符 {boost::mutex::scoped_lock lock(mu);return ++n;}operator T() { return n; } //類型轉換函數,實現atom_increase類型到T類型的隱式轉換private:T n;boost::mutex mu; };int main() { atom_increase<int> n = 0; //隱式轉換:int -> atom_increase++n; //原子前++int i = 5 + n; //隱式轉換:atom_increase ->intreturn 0; } View Code2、遞歸鎖
? recursive_mutex是遞歸鎖,可以多次鎖定,相應的也要多次解鎖。recursive_timed_mutex增加了超時功能。遞歸鎖的使用接口跟互斥鎖基本相同。
3、讀寫鎖
? shared_mutex是讀寫鎖,提供了multiple-reader / single-writer功能。讀取鎖定時我們使用shared_lock<shared_mutex>對象,寫入鎖定時我們使用unique_lock<shared_mutex>對象:
boost::shared_mutex rw_mu;//read thread {boost::shared_lock<boost::shared_mutex> sl(rw_mu); //讀鎖定//...... }//write thread {boost::unique_lock<boost::shared_mutex> ul(rw_mu); //寫鎖定//......} View Code?4、條件變量
? condition_variable_any是條件變量,它用來在一個線程中等待某個事件的發生(滿足某個條件),另一個線程會使條件成立。條件變量需要與一個互斥量配合使用。condition_variable_any::wait()用來等待條件滿足,wait_for()用來等待條件滿足直到超時,wait_until()用來等待條件滿足直到指定的時間, condition_variable_any::notify_one() / notify_all()用來在條件滿足的時候通知條件變量。
??boost中的條件變量的使用方法與posix或windows下條件變量使用方法基本一致:
#include "boost\thread.hpp"boost::condition_variable_any g_cd; boost::mutex g_mu; bool g_bConditionFlag = false;void Thread1Proc() {boost::mutex::scoped_lock lock(g_mu);while (!g_bConditionFlag){boost::this_thread::sleep(boost::posix_time::seconds(1));g_cd.wait(g_mu);}printf("thread1 exit\n"); }int main() {boost::thread t(Thread1Proc);t.detach();boost::this_thread::sleep(boost::posix_time::milliseconds(100));g_mu.lock();g_bConditionFlag = true;g_cd.notify_one();g_mu.unlock();printf("here\n");getchar();return 0; } View Code?5、barrier
? barrier稱為護欄,它可以用來設置線程執行到barrier時必須等待,直到所有線程都達到這個點時才繼續執行。
?6、C++11中的線程操作
? c++11也提供了創建線程和線程同步的方法,c++11里的mutex,與boost里的mutex用法類似:
#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex, std::lock std::mutex foo, bar;void task_a() {// foo.lock(); // bar.lock();std::lock(foo, bar);std::cout << "task a\n";foo.unlock();bar.unlock(); }void task_b() {// bar.lock(); // foo.lock();std::lock(bar, foo);std::cout << "task b\n";bar.unlock();foo.unlock(); }int main() {std::thread th1(task_a);std::thread th2(task_b);// th1.detach();// th2.detach(); th1.join();th2.join();return 0; } View Code? 創建線程的時候需要注意三點:
? ①、如果使用函數對象作為thread的參數的話,直接傳入臨時對象會出錯,可以定義一個對象傳入或者使用lambda表達式:
class CTask { public:void operator()(){int a = 0;} };//std::thread th1(CTask()); //直接傳入臨時對象會出錯 CTask task; std::thread th1(task); th1.join(); View Code? ②、傳遞給線程函數的參數是先保存在于一個中轉站中,當函數執行的時候再傳給函數的形參,而這個時候傳遞的參數指向的值很有可能已經失效,所以,對于線程函數傳遞的參數應該與形參類型相同,而不是再進行轉換。
? ③、如果線程函數的參數是引用的話傳入時還需要結合ref來使用。
void task(int& a, string str){}int iNum = 0;char* pStr = new char[100];strcpy(pStr, "test");//std::thread th(task, 5, std::ref(iNum), pStr); //不應該直接傳入pStrstd::thread th(task, std::ref(iNum), string(pStr)); //應該傳入對應類型delete[] pStr;th.join(); View Code??c++中的lock_guard、unique_lock也是RAII型的互斥鎖,類似boost的scoped_lock,使用示例:
std::lock_guard<std::mutex> _lock(m_mutex);g_num++;??unique_lock在lock_guard的基礎上增加了加鎖和解鎖的接口方法,對比下面的fun1和fun2,二者效果相同,通過代碼可以看出二者區別:
std::mutex g_mu;void fun1() {{std::lock_guard<std::mutex> guard(g_mu);//do something 1 }//do something 2 {std::lock_guard<std::mutex> guard(g_mu);// do something 3 } }void fun2() {std::unique_lock<std::mutex> guard(g_mu);//do something 1 guard.unlock();//do something 2 guard.lock();// do something 3 } View Code??unique_lock可以配合條件變量來使用,而lock_guard不能,因為lock_guard沒有加鎖和解鎖的接口方法。另外,unique_lock和lock_guard都不能復制,unique_lock可以移動,lock_guard不能移動。c++11中的條件變量condition_variable與boost的使用類似,其接口方法有wait()、notify_one()等。
?
轉載于:https://www.cnblogs.com/milanleon/p/7591530.html
總結
以上是生活随笔為你收集整理的boost--线程同步的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: u盘可以自动启动电脑怎么办 U盘自动启动
- 下一篇: 阿里云ECS使用cloudfs4oss挂