使用QMutex :: tryLock和QMutexLocker

时间:2013-12-03 11:23:27

标签: c++ qt concurrency mutex

我有一个后台功能,目前有类似的内容:

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

有没有人有更好的方法可以做到这一点?

谢谢。

3 个答案:

答案 0 :(得分:6)

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() {
    MutexTryLocked locker(_mutex);

    if (!locker.isLocked()) {
        // we didn't get the lock, so return
        return;
    }

    // do some stuff that **could** throw an exception
}

请注意,这个储物柜只是示例代码:生产版本应该是明确不可复制的。


历史记录:JBL的评论提到了一个不再在问题中处理句子的段落。我会把它解释为:

  

......还有其他东西可以锁定互斥锁

如果可能,发生。如果不太可能,只有在部署/扩展/出售给客户后才会发生

答案 1 :(得分:0)

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

答案 2 :(得分:-1)

我想出了另一种不需要编写自己的类的解决方案:

navigationBar