在同一线程上使用 Boost 互斥锁。

我刚开始使用 boost 库,这是一个非常棒的库!同时,我也对互斥锁不太熟悉,如果我犯了新手错误,请多多包涵。

无论如何,我有两个名为 FunctionOneFunctionTwo 的函数。这两个函数由不同的线程异步调用。所以这里发生了什么:在 FunctionOne 中,我在函数开始处锁定全局互斥锁,在函数结束处解锁全局互斥锁。FunctionTwo 同理。

现在问题来了:有时候,FunctionOneFunctionTwo 被调用的时间间隔小于几毫秒(虽然不总是)。所以,FunctionOne 开始执行,半路上 FunctionTwo 执行。当 FunctionTwo 锁定互斥锁时,FunctionOneFunctionTwo 所在的整个线程都被停止,因此 FunctionOne 被卡在半路上,线程在 FunctionTwo 中等待自己,永远无法结束。因此,总结一下:

  • 函数1锁定互斥锁并开始执行代码。
  • 几毫秒后调用函数2并锁定互斥锁,冻结函数1和2所在的线程。
  • 现在,函数1卡在半路上,线程被冻结,所以函数1永远无法完成,互斥锁永远被锁定,等待函数1完成。

在这种情况下应该怎么办?以下是我的代码:

boost::mutex g_Mutex;
lua_State* L;

// 从其他线程调用函数1
void FunctionOne()
{
    g_Mutex.lock();

    lua_performcalc(L);

    g_Mutex.unlock();
}

// 从其他线程几毫秒后调用函数2,冻结线程
// 函数1永远无法完成
void FunctionTwo()
{
    g_Mutex.lock();

    lua_performothercalc(L);

    g_Mutex.unlock();
}
点赞
用户68587
用户68587

这些函数是否有意使其可重入,即FunctionOne在持有mutex时将调用自身或FunctionTwo?反之亦然,FunctionTwo锁定mutex,然后在mutex保持锁定状态时调用FunctionOne/FunctionTwo?

  • 如果不是这样,请勿从同一线程调用这两个函数。如果您打算FunctionTwo阻塞直到FunctionOne完成,则在同一个线程中调用它是错误的。如果lua_performcalc最终调用FunctionTwo,则会发生这种情况。这将是它们可以在同一线程上调用的唯一方式。

  • 如果是这样,请使用recursive_mutex。常规mutex只能锁定一次;从同一线程再次锁定会导致错误。recursive_mutex可以被单个线程多次锁定,并在线程调用相同的unlock数量时锁定。

在任何情况下,请避免显式调用lock和unlock。如果抛出异常,则mutex不会被解锁。最好使用RAII式锁定,如下所示:

{
    boost::recursive_mutex::scoped_lock lock(mutex);

    ...critical section code...

    // mutex is unlocked when 'lock' goes out of scope
}
2012-12-10 17:46:22
用户1858151
用户1858151

你的描述是错误的。一个 mutex 不能被两次锁定。你有一个不同的问题。

  • 在 mutex 被锁定时检查是否可重入。
  • 检查异常。

为了避免异常问题,你应该使用 boost::mutex::scoped_lock(RAAI)来锁定。

2012-12-10 17:59:41