使用互斥锁和手动锁定互斥锁的区别

LeC*_*Coc 5 c++ qt multithreading

具体来说,在 const 成员函数中,如果我mutex.lock()在它的开头和mutex.unlock()返回之前使用,在 OpenMP 循环中运行它时会崩溃。但是如果我QMutexLocker(&mutex)在函数的开头用一个替换这两个调用,它运行起来很顺利。Visual Studio 2010,Qt 4.8。我希望这两个代码是等价的,但显然不是。我在这里缺少什么?

编辑:虽然这不会重现问题,但一个小例子:

class TileCache
{
public:
    bool fillBuffer(const std::string& name) const {
        //QMutexLocker lock(&mCacheMutex);
        mCacheMutex.lock();
        auto ite = mCache.find(name);
        if(ite == mCache.end())
            mCache.insert(ite, std::make_pair(name, new unsigned char[1024]));
        // code here
        mCacheMutex.unlock();
        return true;
    }
private:
    mutable std::map<std::string, unsigned char*> mCache;
    mutable QMutex mCacheMutex;
};

int main(int argc, char *argv[])
{
    std::cout << "Test" << std::endl;
    TileCache cache;
#pragma omp parallel for shared(cache)
    for(int i = 0; i < 2048; ++i)
    {
        cache.fillBuffer("my buffer");
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我基本上是在问是否有任何已知的理由相信这两种方式是不等价的,如果总是调用lock()/ unlock()(没有lock()匹配的调用unlock())QMutexLocker在某些情况下的行为与,不同。

650*_*502 5

Locker 对象的优点是自动处理所有退出点,包括由异常引起的退出点。

通常,忘记退出点或异常只会使互斥体锁定,症状是程序挂起。

如果您遇到崩溃,那么问题出在其他地方,并且您在使用储物柜对象时看到问题消失的事实只是巧合(如果发生崩溃,则程序肯定有错误,如果没有崩溃,则不能说程序是正确的......尤其是在像 C++ 这样的语言中,有“未定义行为”的概念)。

编辑

另一个不明显的优点是,使用作为第一个语句创建的锁对象,可以保证解锁将作为返回调用者之前的最后一件事发生。如果函数内部创建了依赖于互斥体的其他对象,这可能会产生影响:

void ok_func() {
    Locker mylock(mymutex);
    Obj myobj; // constructor and destructor require the lock
}

void buggy_func() {
    lock(mymutex);
    Obj myobj; // constructor and destructor require the lock
    unlock(mymutex);
    // Bug: myobj instance will be destroyed without the lock
}


void workaround_func() {
    lock(mymutex);
    {   // nested scope needed
        Obj myobj; // constructor and destructor require the lock
    }
    unlock(mymutex);
}
Run Code Online (Sandbox Code Playgroud)

  • @LeCoc:很高兴听到您发现了问题。事实上,这是使用储物柜对象的另一个不明显的优势。由于销毁以与构造相反的顺序发生,如果您在输入时创建储物柜,您还可以保证解锁将在离开函数之前发生(即也在执行所有其他本地实例析构函数之后)。编辑答案以更清楚地显示这一点...... (2认同)