1. 程式人生 > >C++11 thread 及互斥鎖、條件變數

C++11 thread 及互斥鎖、條件變數

啟動的格式: #include <thread>//包含標頭檔案 void fucntion();//定義一個執行緒執行的函式 thread t1(fucntion);//執行緒啟動這個函式 //一建立就自動執行,主執行緒非阻塞 void factorial(int n,char b,..);//帶引數的函式,引數的個數順延 thread t2(factorial,5,'a',..);//執行緒啟動帶引數的函式 t1.join(); //阻塞 執行緒一些控制函式: Join() :讓主執行緒等待 阻塞 t1.join(); Detach():非阻塞(預設) t1.detach();//最好寫上
Move() :轉移、竊取 thread t2 = move(t1); //執行緒無法賦值,只能被轉移相當於換個名字,但轉移後的t1無值 Ref() :執行緒傳遞引數傳遞的是引用,n為引數(需要互鎖,存在資料競爭) thread t1(fucntion,ref(n)); 使用互斥同步執行緒: 假如多個執行緒同時爭奪cout資源,則結果輸出無序,這時就需要使用互斥物件mutex。注意可能會出現死鎖。 #include <mutex>//包含標頭檔案 mutex mut;//定義一個互斥變數 mut.lock();//上鎖 cout << "我是通過主執行緒執行的" << i << endl;
mut.unlock();//解鎖 mutex的封裝 Lock_guard unique_lock: lock_guard 把鎖放到lock_guard中時,mutex自動上鎖,lock_guard析構時,同時把mutex解鎖 void share_print(string msg, int id) { lock_guard<mutex> guard(mut); cout << msg << " id = " << id << endl; } unique_lock 第三種方式加鎖:unique_lock 更有彈性
缺點:消耗更多系統資源 1 unique_lock<mutex> locker(m_mutex);//自動上鎖 cout << str << i << endl; //解鎖 locker.unlock(); //。。。進行其他操作 更彈性 2 defer_lock表示不對mutex加鎖,只管理mutex,此時mutex是沒有加鎖的 unique_lock<mutex> locker(m_mutex,defer_lock); //本區間未上鎖 locker.lock(); cout << str << i << endl;//上鎖 //解鎖 locker.unlock(); //。。。進行其他操作 更彈性 3 lock_gard 無法複製(=) 無法移動 unique_lock 可以被移動 mutex會被轉移,原先的失效 unique_lock<mutex> lokcer = move(locker1); 缺點:消耗更多效能 unique_lock更有彈性,lock_gard效能更優 unique_lock內部持有mutex的狀態:locked,unlocked。unique_lock比lock_guard佔用空間和速度慢一些,因為其要維護mutex的狀態。 死鎖: 什麼叫死鎖? 執行緒A和B互相等待各自持有的資源釋放,進入死迴圈。 死鎖產生 例如: //一個執行緒中 lock_guard<mutex> guard1(m_mutex2);//執行成功 mutex2成功上鎖 lock_guard<mutex> guard(m_mutex1);//等待mutex1解鎖 //另一個執行緒 lock_guard<mutex> guard1(m_mutex1);//執行成功 mutex1成功上鎖 lock_guard<mutex> guard(m_mutex2);//等待mutex2解鎖 //則有可能死鎖 解決方案 1:只使用一個mutex 2:保證 locker順序相同 //一個執行緒中(先執行) lock_guard<mutex> guard1(m_mutex1);//執行成功 mutex1成功上鎖 lock_guard<mutex> guard(m_mutex2);//等待mutex1解鎖 //另一個執行緒 lock_guard<mutex> guard1(m_mutex1);//等待mutex1解鎖 lock_guard<mutex> guard(m_mutex2);//等待mutex2解鎖 3:使用lock() std::lock會使用一種避免死鎖的演算法對多個待加鎖物件進行lock操作,當待加鎖的物件中有不可用物件時std::lock會阻塞當前執行緒知道所有物件都可用。 lock(m_mutex1, m_mutex2); lock_guard<mutex> guard1(m_mutex2, adopt_lock); lock_guard<mutex> guard(m_mutex, adopt_lock); //adopt_lock相當於讓lock()接手控制 4:清楚你寫的程式碼,避免產生此問題 條件變數 std::condition_variable  當std::condition_variable 物件的某個 wait 函式被呼叫的時候,它使用 std::unique_lock(通過 std::mutex) 來鎖住當前執行緒。當前執行緒會一直被阻塞,直到另外一個執行緒在相同的 std::condition_variable 物件上呼叫了notification 函式來喚醒當前執行緒。 notify_one()  喚醒一個在等待執行緒 notify_all()喚醒所有等待的執行緒 condition_variable cond; cond.wait(locker); cond.notify_one();