Using QMutex::tryLock and QMutexLocker

Using QMutex::tryLock and QMutexLocker

本文关键字:QMutexLocker and tryLock Using QMutex      更新时间:2023-10-16

我有一个后台函数,目前有如下内容:

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减速之间的某个时候,可能会出现其他东西并锁定互斥锁。

有人对更好的方法有什么建议吗?

谢谢。

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
}

请注意,这个locker只是示例代码:生产版本可能是显式不可复制的。


历史注释:JBL的评论提到了一段针对不再存在问题的句子的内容。我将其改写为:

其他东西可能会出现并锁定互斥

如果可能的话,它发生。如果不太可能,只有在部署/扩大规模/将其出售给客户后,才会发生

我也遇到过类似的情况,最终使用了等效的标准组件而不是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
}