我有一个背景函数,目前有如下所示:
void SomeClass::someFunction()
{
if (!_mutex.tryLock())
{
// i want to know the mutex is locked, and then exit the function
return;
}
else
{
_mutex.unlock();
}
QMutexLocker locker(_mutext);
// do some stuff that **could** throw an exception
}我的两难处境与_mutex.unlock()和QMutextLocker的声明有关。
如果_mutex是锁定的,那么我想知道它。如果不是,那我就把它锁上。问题是,我希望使用QMutexLocker来锁定大部分函数的_mutex。函数可能会抛出异常,因此手动解锁_mutex可能很困难,而且容易出错。
上面的解决方案是可行的,但我担心的是,在_mutex.unlock()和QMutexLocker减速之间的某个时间,可能会出现一些其他的东西,并锁定互斥对象。
有谁有更好的方法做这件事吗?
谢谢。
发布于 2013-12-03 11:46:47
QMutexLocker显然不能完全满足您的需要,但是您可以很容易地编写自己的RAII包装器:
class MutexTryLocker {
QMutex &m_;
bool locked_;
public:
MutexTryLocker(QMutex &m) : m_(m), locked_(m.tryLock()) {}
~MutexTryLocker() { if (locked_) m_.unlock(); }
bool isLocked() const { return locked_; }
}然后像这样使用它:
void SomeClass::someFunction() {
MutexTryLocker locker(_mutex);
if (!locker.isLocked()) {
// we didn't get the lock, so return
return;
}
// do some stuff that **could** throw an exception
}注意,这个储物柜只是示例代码:一个生产版本可能是显式不可复制的。
历史注释:JBL的评论提到了一个段落,该段落不再涉及问题中的一个句子。我将把它解释为:
..。可能会有别的东西来锁定互斥体
如果有可能,它就会发生。如果不太可能,它只会发生在您部署它/放大它/向客户出售它之后。
发布于 2020-10-27 16:29:25
我也遇到过类似的情况,最终使用了等效的标准组件而不是Qt组件,因为它们的lock_guard能够处理已经锁定的互斥对象。如果这是某人的选择,你可以这样做:
#include <mutex>
std::mutex _mutex;
void SomeClass::someFunction()
{
if (!_mutex.try_lock())
{
// i want to know the mutex is locked, and then exit the function
return;
}
// The lock_guard overtakes the already locked mutex
const std::lock_guard<std::mutex> locker(_mutex, std::adopt_lock);
// do some stuff that **could** throw an exception
}https://stackoverflow.com/questions/20349787
复制相似问题