[英]Is the execution of a c++ 11 atomic object also atomic ?
我有一個對象,其所有功能應按順序執行。 我知道可以使用互斥鎖來做到這一點
#include <mutex>
class myClass {
private:
std::mutex mtx;
public:
void exampleMethod();
};
void myClass::exampleMethod() {
std::unique_lock<std::mutex> lck (mtx); // lock mutex until end of scope
// do some stuff
}
但是使用此技術時,在exampleMethod中調用其他互斥鎖方法后會發生死鎖。
所以我正在尋找更好的分辨率。 默認的std :: atomic訪問是順序一致的,因此不可能同時讀取對該對象的寫入,但是現在當我訪問對象並調用方法時,整個函數調用是否也是原子的或更多類似的東西
object* obj = atomicObj.load(); // read atomic
obj.doSomething(); // call method from non atomic object;
如果是,有沒有比使用互斥鎖鎖定大多數功能更好的方法了?
停下來想一想何時實際需要鎖定互斥鎖。 如果您有一些在許多其他函數中調用的輔助函數,則它可能不應嘗試鎖定互斥鎖,因為調用者已經擁有了。
如果在某些情況下沒有被另一個成員函數調用,因此確實需要獲取鎖,請提供一個實際執行該操作的包裝器函數。 具有兩個版本的成員函數,公共foo()
和私有fooNoLock()
並不罕見,其中:
public:
void foo() {
std::lock_guard<std::mutex> l(mtx);
fooNoLock();
}
private:
void fooNoLock() {
// do stuff that operates on some shared resource...
}
根據我的經驗,遞歸互斥是一種代碼味道 ,表明作者並沒有真正意識到使用函數的方式-並非總是錯誤的,但是當我看到一個時,我就感到可疑。
至於原子運算,它們實際上只能應用於較小的算術運算,例如遞增整數或交換2個指針。 這些操作不是自動的原子操作,但是當您使用原子操作時,它們是可以用於這些操作的種類。 您肯定對單個原子對象上的2個獨立操作沒有任何合理的期望。 在兩次操作之間可能發生任何事情。
您可以改用std :: recursive_mutex 。 這將使已擁有的線程互斥以重新獲取它而不會阻塞。 但是,如果另一個線程嘗試獲取該鎖,它將阻塞。
正如@BoBTFish正確指出的那樣,最好將您的類的公共接口分開,該成員函數獲取非遞歸鎖,然后調用那些非遞歸鎖。 然后,您的代碼必須假定在運行私有方法時始終保持鎖定。
為了安全起見,您可以向每個需要保持鎖的方法添加對std::unique_lock<std::mutex>
的引用。
因此,即使您碰巧從另一個調用一個私有方法,也需要確保互斥體在執行之前被鎖定:
class myClass
{
std::mutex mtx;
//
void i_exampleMethod(std::unique_lock<std::mutex> &)
{
// execute method
}
public:
void exampleMethod()
{
std::unique_lock<std::mutex> lock(mtx);
i_exampleMethod(lock);
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.