C++標准庫之mutex


互斥鎖有可重入、不可重入之分。C++標准庫中用mutex表示不可重入的互斥鎖,用recursive_mutex表示可重入的互斥鎖。為這兩個類增加根據時間來阻塞線程的能力,就又有了兩個新的互斥鎖:timed_mutex(不可重入的鎖)、recursive_timed_mutex(可重入的鎖)。

互斥鎖單獨使用時主要是為了使對共享資源的互斥使用,即同時只能有一個線程使用,以防止同時使用可能造成的數據問題。

C++標准庫的所有mutex都是不可拷貝的,也不可移動。

mutex基本操作

上鎖 lock 如果mutex未上鎖,則將其上鎖。否則如果已經其它線程lock,則阻塞當前線程。

上鎖 try_lock 如果mutex未上鎖,則將其上鎖。否則返回false,並不阻塞當前線程。

解鎖 unlock  如果mutex被當前線程鎖住,則將其解鎖。否則,是未定義的行為。

timed_mutex在mutex的基礎上增加了以下兩個操作

try_lock_for(duration) 如果timed_mutex未上鎖,則將其上鎖,否則阻塞當前線程,但最長只阻塞duration表示的時間段。

try_lock_until(time_point) 如果timed_mutex未上鎖,則將其上鎖,否則阻塞當前線程,但最長只會阻塞到time_point表示的時間點就不再阻塞。

try_lock_for/until可以檢測到死鎖的出現,這是目前想到的一種用途。

if(!try_lock_for(chrono::hours(1)))
{
  throw "出現死鎖!";  
}

可重入的鎖 recursive_mutex、recursive_timed_mutex與對應的mutex、timed_mutex操作一致。不同點在於,不可重入的鎖在lock或try_lock一個已經被當前線程lock的鎖時會導致死鎖,而可重入的鎖不會。

 

輔助類

template<class Mutex> class lock_guard;

lock_guard用於脫離lock_guard對象生存期后自動對互斥鎖進行解鎖操作。

explicit lock_guard(mutex_type &m);對象創建時執行 m.lock(),對象銷毀時執行 m.unlock()

explicit lock_guard(mutex_type &m,adpot_lock_t tag);對象創建不執行lock,對象銷毀時執行 m.unlock()。所以m應該是一個已經被當前線程lock的互斥鎖。

template<class Mutex> class unique_lock;

unique_lock()noexcept;不管理任何鎖。

explicit unique_lock(mutex_type &m);對象創建時執行 m.lock()。

unique_lock(mutex_type &m,try_to_lock_t tag);對象創建時執行 m.try_lock()。

unique_lock(mutex_type &m,defer_lock_t tag);對象創建時不進行上鎖操作,m要滿足沒有被當前線程鎖住的條件。

unique_lock(mutex_type &m,adopt_lock_t tag);對象創建時不進行上鎖操作,m要滿足已經被當前線程鎖住的條件。

unique_lock(mutex_type &m,const duration & real_time);對象創建時執行 m.try_lock_for(real_time)。

unique_lock(mutex_type &m,const time_point & abs_time);對象創建時執行 m.try_lock_until(abs_time)。 

unique_lock(unique_lock &&);移動構造

操作:unique_lock具備它所管理的鎖的所有操作 lock、unlock、try_lock、try_lock_for、try_lock_until。

mutex_type *release(); 不再管理互斥鎖。

void swap(unique_lock &);交換管理的互斥鎖。

bool owns_lock() 用於探測unique_lock是否管理着一個互斥鎖且其處於上鎖狀態。bool operate bool() 與owns_lock等同。

mutex_type * mutex();用於返回管理的互斥鎖的指針,但仍對其進行管理。

在unique_lock銷毀的時候,owns_lock為真才會執行unlock。

總的來說,lock_guard在時空間效率上比較高,但功能單一。unique_lock功能多,使用靈活,但時空間效率不如lock_guard。如果使用了輔助類來管理互斥鎖,就不要直接操作鎖了,否則容易引發混亂,產生BUG。

 

輔助函數

template <class Mutex1, class Mutex2, class... Mutexes>
int try_lock (Mutex1& a, Mutex2& b, Mutexes&... cde);

根據參數順序對多個鎖進行上鎖,如果成功鎖住所有鎖,返回-1,返回值大於0表示失敗的鎖的位置號。

 

template <class Mutex1, class Mutex2, class... Mutexes>
void lock (Mutex1& a, Mutex2& b, Mutexes&... cde);

對多個鎖進行上鎖,該函數是阻塞的。另,它保證發生異常的情況下已經上鎖的鎖會被解鎖。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM