1. 程式人生 > 實用技巧 >C++ 執行緒互斥

C++ 執行緒互斥

競態條件:多執行緒執行結果應該是一致的,不應該因CPU 對執行緒的呼叫順序不一樣,而導致結果不一樣,這也是多執行緒對全域性量的共享,導致資料不一致,因此要保證執行緒的安全

例子如下:

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<unistd.h>
#include<list>
#include<thread>
using namespace std;
int count = 100;

// 模擬賣票的執行緒函式
void SellTicket(int i) { while(count>0) { cout<<"視窗"<<i<<"賣出第"<<count<<"張票"<<endl; count--; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } } int main() { list<std::thread> tlist; for(int i = 0 ;i < 3; i++) { tlist.push_back(std::thread(SellTicket,i)); }
for(std::thread &t : tlist) { t.join(); } cout<<"所有視窗完成賣票"<<endl; return 0; }

當把資料從記憶體讀到暫存器中,通過運算單元計算完,並沒有寫回記憶體,這個執行緒被掛起,那麼就會導致記憶體中的資料沒有被修改,因此需要使用互斥鎖。

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<unistd.h>
#include
<list> #include<thread> #include<mutex> using namespace std; int count = 100; std::mutex mtu; // 模擬賣票的執行緒函式 void SellTicket(int i) { while(count>0) { mtu.lock(); // 這裡還是存在問題,當count 為1 的時候,此時有兩個執行緒都進來,但是一個執行緒沒有真正的進行count-- , 那麼另一個執行緒阻塞在lock() ,當 // 第一個執行緒釋放鎖之後,那麼第二個執行緒還是會進行count-- ,不正確。 // 因此需要鎖加雙層判斷 if(count >0 ) { cout<<""<<i<<"視窗:"<<count<<endl; count--; } mtu.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } int main() { list<std::thread> tlist; for(int i = 0 ;i < 3; i++) { tlist.push_back(std::thread(SellTicket,i)); } for(std::thread &t : tlist) { t.join(); } cout<<"所有視窗完成賣票"<<endl; return 0; }

這裡就使用了 std::mutex

這裡有點像智慧指標一樣管理互斥鎖 lock_guard (是個類 接收一個互斥鎖) // 類似於智慧指標的scoped_ptr

例如 :std::mutex mut;

lock_guard<std::mutex> lock(mut); // 保證unlock() 一定被呼叫到,不會造成死鎖

當出作用域就析構,也就是釋放鎖

unique_lock 允許右值引用的拷貝構造和賦值

unique_lock<std::mutex> _lock(mut):

_lock.lock();

_lock.unlock();