C++11多線程-mutex(1)

mutex又稱互斥量,用于提供對共享變量的互斥訪問。C++11中mutex相關(guān)的類都在<mutex>頭文件中。共四種互斥類:

序號 名稱 用途
1 std::mutex 最基本也是最常用的互斥類
2 std::recursive_mutex 同一線程內(nèi)可遞歸(重入)的互斥類
3 std::timed_mutex 除具備mutex功能外,還提供了帶時限請求鎖定的能力
4 std::recursive_timed_mutex 同一線程內(nèi)可遞歸(重入)的timed_mutex

與std::thread一樣,mutex相關(guān)類不支持拷貝構(gòu)造、不支持賦值。同時mutex類也不支持move語義(move構(gòu)造、move賦值)。不用擔(dān)心會誤用這些操作,真要這么做了的話,編譯器會阻止你的。

一、lock, try_lock, unlock

mutex的標(biāo)準(zhǔn)操作,四個mutex類都支持這些操作,但是不同類在行為上有些微的差異。

1.1 lock

鎖住互斥量。調(diào)用lock時有三種情況:

  1. 如果互斥量沒有被鎖住,則調(diào)用線程將該mutex鎖住,直到調(diào)用線程調(diào)用unlock釋放。
  2. 如果mutex已被其它線程lock,則調(diào)用線程將被阻塞,直到其它線程unlock該mutex。
  3. 如果當(dāng)前mutex已經(jīng)被調(diào)用者線程鎖住,則std::mutex死鎖,而recursive系列則成功返回。

1.2 try_lock

嘗試鎖住mutex,調(diào)用該函數(shù)同樣也有三種情況:

  1. 如果互斥量沒有被鎖住,則調(diào)用線程將該mutex鎖住(返回true),直到調(diào)用線程調(diào)用unlock釋放。
  2. 如果mutex已被其它線程lock,則調(diào)用線程將失敗,并返回false。
  3. 如果當(dāng)前mutex已經(jīng)被調(diào)用者線程鎖住,則std::mutex死鎖,而recursive系列則成功返回true。

1.3 unlock

解鎖mutex,釋放對mutex的所有權(quán)。值得一提的時,對于recursive系列mutex,unlock次數(shù)需要與lock次數(shù)相同才可以完全解鎖。
下面給出一個mutex小例子

#include <iostream>
#include <thread>
#include <mutex>

void inc(std::mutex &mutex, int loop, int &counter) {
    for (int i = 0; i < loop; i++) {
        mutex.lock();
        ++counter;
        mutex.unlock();
    }
}
int main() {
    std::thread threads[5];
    std::mutex mutex;
    int counter = 0;

    for (std::thread &thr: threads) {
        thr = std::thread(inc, std::ref(mutex), 1000, std::ref(counter));
    }
    for (std::thread &thr: threads) {
        thr.join();
    }

    // 輸出:5000,如果inc中調(diào)用的是try_lock,則此處可能會<5000
    std::cout << counter << std::endl;

    return 0;
}
//: g++ -std=c++11 main.cpp

二、try_lock_for, try_lock_until

這兩個函數(shù)僅用于timed系列的mutex(std::timed_mutex, std::recursive_timed_mutex),函數(shù)最多會等待指定的時間,如果仍未獲得鎖,則返回false。除超時設(shè)定外,這兩個函數(shù)與try_lock行為一致。

// 等待指定時長
template <class Rep, class Period>
    try_lock_for(const chrono::duration<Rep, Period>& rel_time);
// 等待到指定時間
template <class Clock, class Duration>
    try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);

try_lock_for相關(guān)代碼

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

void run500ms(std::timed_mutex &mutex) {
    auto _500ms = std::chrono::milliseconds(500);
    if (mutex.try_lock_for(_500ms)) {
        std::cout << "獲得了鎖" << std::endl;
    } else {
        std::cout << "未獲得鎖" << std::endl;
    }
}
int main() {
    std::timed_mutex mutex;

    mutex.lock();
    std::thread thread(run500ms, std::ref(mutex));
    thread.join();
    mutex.unlock();

    return 0;
}
//輸出:未獲得鎖

三、其它

mutex文件中還提供了lock_guard, unique_lock,std::call_once, std::try_lock, std::lock(批量上鎖)操作,由于篇幅關(guān)系,我們下次再講。

上一篇
C++11多線程(簡約但不簡單)
目錄 下一篇
C++11多線程-mutex(2)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容