1. 程式人生 > >執行緒與互斥鎖(C++11中std::thread和std::mutex的用法)

執行緒與互斥鎖(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 啟動一個執行緒的方法:

兩種情況:

  1. 控制代碼定義和執行緒啟動分開
    執行緒控制代碼 = std::thread(引數);
  2. 在定義執行緒控制代碼的同時啟動執行緒
    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;};

  1. 引數可以是lamda表示式
    m_thrProcess = std::thread([this](){this->process(); });
    若process需要傳進去引數,可以傳遞函式引數:
    m_thrProcess = std::thread([this](函式引數){this->process(函式引數); });

  2. 引數可以是普通的函式(相對類的成員函式而言)
    std::thread m_thrProcess(test); //沒有函式引數
    std::thread m_thrProcess(test,函式引數); //有函式引數

  3. 引數可以是類的成員函式
    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(); //解鎖