執行緒與互斥鎖(C++11中std::thread和std::mutex的用法)
執行緒
0
首先是曾經在MultiCMOS專案中用到的:
#include <thread> //包含標頭檔案
class IDataProcessUnit
{
protected:
bool m_processing{ false }; //執行緒退出標識
std::thread m_thrProcess; //執行緒控制代碼
public:
//資料處理流程在此
virtual void process() {
}
//解構函式,物件不存在了則停止當前執行緒
virtual ~IDataProcessUnit() {
stop();
}
//啟動
virtual bool start() {
if (m_processing)
return false;
m_processing = true;
m_thrProcess = std::thread([this](){this->process(); });
return true;
}
//停止
virtual void stop() {
m_processing = false;
std::this_thread::sleep_for(std ::chrono::milliseconds(50));
if (m_thrProcess.joinable())
m_thrProcess.join();
}
};
重點:
執行緒控制代碼,用來唯一標識執行緒
執行緒函式,執行緒的入口函式。當執行緒執行完執行緒函式後,執行緒也會退出。如果不傳入執行緒函式(類似這種形式std::thread t;),執行緒不會執行。執行緒函式不能過載,否則不能編譯。
執行緒退出標識,判斷當前執行緒是否正在執行
1 啟動一個執行緒的方法:
兩種情況:
- 控制代碼定義和執行緒啟動分開
執行緒控制代碼 = std::thread(引數);
- 在定義執行緒控制代碼的同時啟動執行緒
std::thread m_thrProcess(引數);
幾種將執行緒控制代碼與執行緒函式繫結到一起的情況
簡單介紹一下lamda表示式:
lamda表示式表示一個可呼叫的程式碼單元。
[capture list](parameter list)->return type{function body}
capture list: 在函式中定義的區域性變數的列表。
parameter list: 引數列表。
return type: 返回型別。
function body: 函式體。
可以忽略引數列表和返回型別。如:
auto f = [] {return 42;};
引數可以是lamda表示式
m_thrProcess = std::thread([this](){this->process(); });
若process需要傳進去引數,可以傳遞函式引數:
m_thrProcess = std::thread([this](函式引數){this->process(函式引數); });
引數可以是普通的函式(相對類的成員函式而言)
std::thread m_thrProcess(test);
//沒有函式引數
std::thread m_thrProcess(test,函式引數);
//有函式引數引數可以是類的成員函式
std::thread m_thrProcess(&類名::函式名, &類物件);
std::thread m_thrProcess(&類名::函式名, &類物件, 函式引數);
2 銷燬一個執行緒物件
std::thread::joinable()
去銷燬一個仍然可以“joinable”的C++執行緒物件會被認為是一種錯誤。為了銷燬一個C++執行緒物件,要麼join()函式需要被呼叫(並結束),要麼detach()函式被呼叫。如果一個C++執行緒物件當銷燬時仍然可以被join,異常會被丟擲。
呼叫 join 或 detach 之前需要呼叫 joinable() 判斷一下執行緒是否執行。如果 joinable() 返回 false,則不需要。
std::thread::join()
當thread::join()函式被呼叫後,呼叫它的執行緒會被阻塞,直到執行緒的執行被完成。基本上,這是一種可以用來知道一個執行緒已結束的機制。當thread::join()返回時,執行的執行緒已經完成,C++執行緒物件可以被銷燬。
一般情況下還是請使用join而非detach。
std::thread::detach()
當thread::detach()函式被呼叫後,執行的執行緒從執行緒物件中被分離,已不再被一個執行緒物件所表達——這是兩個獨立的事情。C++執行緒物件可以被銷燬,同時OS執行的執行緒可以繼續。如果程式想要知道執行的執行緒何時結束,就需要一些其它的機制。join()函式在那個thread物件上不能再被呼叫,因為它已經不再和一個執行的執行緒相關聯。
互斥鎖
#include <mutex>
std::mutex m1; //執行緒互斥物件
m1.lock(); //加鎖
m1.unlock(); //解鎖