互斥執行緒安全

當多個執行緒嘗試訪問資源時可能會出現問題。舉一個簡單的例子,假設我們有一個向變數新增一個的執行緒。它通過首先讀取變數,向其中新增一個變數然後將其儲存回來來完成此操作。假設我們將此變數初始化為 1,然後建立此執行緒的兩個例項。兩個執行緒完成後,直覺表明此變數的值應為 3.但是,下表說明了可能出錯的地方:

執行緒 1 執行緒 2
時間步驟 1 從變數中讀取 1
時間步驟 2 從變數中讀取 1
時間步驟 3 加 1 加 1 得到 2
時間步驟 4 加 1 加 1 得到 2
時間步驟 5 將 2 儲存到變數中
時間步驟 6 將 2 儲存到變數中

如你所見,在操作結束時,2 位於變數中,而不是 3.原因是執行緒 2 線上程 1 完成更新之前讀取變數。解決方案?互斥。

互斥體(mutman of mut ual ex clusion)是一個旨在解決此類問題的資源管理物件。當執行緒想要訪問資源時,它獲取資源的互斥鎖。一旦完成訪問資源,執行緒就釋放互斥鎖。獲取互斥鎖時,在釋放互斥鎖之前,所有獲取互斥鎖的呼叫都不會返回。為了更好地理解這一點,可以將互斥鎖視為超市中的等待線:執行緒通過嘗試獲取互斥鎖然後等待它們前面的執行緒完成,然後使用資源,然後走出釋放互斥鎖。如果每個人都試圖立即訪問資源,那麼就會出現完全的混亂局面。

Version >= C++ 11

std::mutex 是 C++ 11 的互斥體實現。

#include <thread>
#include <mutex>
#include <iostream>
using namespace std;

void add_1(int& i, const mutex& m) { // function to be run in thread
    m.lock();
    i += 1;
    m.unlock();
}

int main() {
    int var = 1;
    mutex m;

    cout << var << endl; // prints 1
    
    thread t1(add_1, var, m); // create thread with arguments
    thread t2(add_1, var, m); // create another thread
    t1.join(); t2.join(); // wait for both threads to finish
    
    cout << var << endl; // prints 3
}