![](/img/trans.png)
[英]std::unique_lock<std::mutex> or std::lock_guard<std::mutex>?
[英]Using mutex, lock_guard, unique_lock properly in a class
我正在嘗試更好地理解與類一起使用時的std::mutex
, std::lock_guard
, std::unique_lock
。
對於初學者,我有點了解lock_guard
和unique_lock
之間的區別:我知道lock_guard
僅在構造上鎖定互斥鎖,這是在類成員函數中使用它的首選用法:
class Foo {
std::mutex myMutex;
public:
void someFunc() {
std::lock_guard<std::mutex> guard( myMutex );
// code
}
};
像上面一樣,具有類成員myMutex的lock_guard將在函數Foo::someFunc()
的作用域的開始處鎖定,然后在代碼離開作用域之后由於lock_guard
和mutex
的析構函數而被解鎖。
我也知道unique_lock
允許您多次鎖定和解鎖互斥鎖。
我的問題是關於一個課堂設計的地方。 如果我希望互斥鎖被鎖定在該類的構造函數中,那么在constructor
超出范圍時不要使其解鎖,而是在調用該類的析構函數時使其解鎖...
class Foo {
std::mutex myMutex;
public:
Foo() {
// lock mutex here;
}
~Foo() {
// unlock mutex here;
}
};
可以實現以上目標嗎? 如果可以,怎么辦?
在上面的最后一個示例中,我不確定的是:如果在類的構造函數中使用了lock_guard; 在構造函數離開作用域之后,或者當類的對象超出作用域時調用類的析構函數時,它將超出作用域嗎? 我想嘗試模仿所示第二個示例的預期行為。
發布此問題后:我做了一些研究,並做了一些試驗和錯誤。 因此,我選擇了不同的實現和解決方案。
最終我沒有使用最初的建議,而是使用了std::shared_mutex
和std:shared_lock
。
因此,在類的標題中,我沒有保存或存儲任何mutex
。 現在在我班的cpp文件中。 我正在使用靜態全局shared_mutex
所以我的課現在看起來像這樣:
Foo.cpp
#include "Foo.h"
#include <mutex>
std::mutex g_mutex;
Foo::Foo() {
// code not locked
{ // scope of guard
std::lock_guard<std::mutex> lock( g_mutex );
// code to lock
} // end scope destroy guard unlock mutex
// other class code
}
Foo::someFunc() {
// Code to lock
std::lock_guard<std::mutex> lock( g_mutex );
}
我發現了為什么它對我來說無法正常工作。 在我的類的構造函數中,它是從其父類或基類中調用一個函數。 然后,父類或基類正在調用該類的靜態成員,而該類的靜態成員函數也在同一互斥鎖上使用lock_guard。
我發現問題后; 我有兩個選擇。 我可以使用2個獨立的互斥體,一個專門用於構造函數,一個專門用於靜態方法。 經過一番思考,如果我使用2,我算好了,而且我阻塞了整個構造函數,直到類實例被銷毀為止,當前的鎖和互斥才不會超出范圍。 但是,類的壽命幾乎是應用程序的整個壽命。 然后,如果我在static方法中使用了另一個互斥鎖和鎖保護,那么將另一個lock_guard包裹在現有的那個上將是多余的。 因此,我得出的結論是,我需要為需要被互斥鎖阻止的代碼創建一個有范圍的塊{ }
,以便可以在本節超出范圍后將其解鎖,然后構造函數可以自由調用static方法,並且可以重用與現在免費的相同的互斥量。 該類現在可以正常工作,並且在不應該發生的情況下不會崩潰也不會引發異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.