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時有三種情況:
- 如果互斥量沒有被鎖住,則調(diào)用線程將該mutex鎖住,直到調(diào)用線程調(diào)用unlock釋放。
- 如果mutex已被其它線程lock,則調(diào)用線程將被阻塞,直到其它線程unlock該mutex。
- 如果當(dāng)前mutex已經(jīng)被調(diào)用者線程鎖住,則std::mutex死鎖,而recursive系列則成功返回。
1.2 try_lock
嘗試鎖住mutex,調(diào)用該函數(shù)同樣也有三種情況:
- 如果互斥量沒有被鎖住,則調(diào)用線程將該mutex鎖住(返回true),直到調(diào)用線程調(diào)用unlock釋放。
- 如果mutex已被其它線程lock,則調(diào)用線程將失敗,并返回false。
- 如果當(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) |
|---|