我有一个对象,其所有功能应按顺序执行。我知道可以用互斥锁来做到这一点
#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个单独的操作,您当然不能有任何合理的期望。在两次操作之间可能发生任何事情。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句