4

我是 boost 库的新手,这是一个非常棒的库!另外,我是互斥锁的新手,如果我犯了新手错误,请原谅我。

无论如何,我有两个函数叫做FunctionOneand FunctionTwoFunctionOne并由FunctionTwo不同的线程异步调用。所以这就是发生的事情:在FunctionOne中,我在函数的开头锁定了一个全局互斥锁,并在函数的末尾解锁了全局互斥锁。同样的事情FunctionTwo

现在问题来了:有时,FunctionOne并且FunctionTwo相隔不到几毫秒的时间被调用(但并非总是如此)。因此,FunctionOne开始执行并执行到一半FunctionTwo。当锁定互斥锁时,FunctionTwo 整个线程都停止了,所以中途卡住了,线程永远等待自己。所以,总结一下:FunctionOneFunctionTwoFunctionOneFunctionTwo

  • 函数 1 锁定互斥体并开始执行代码。
  • 函数 2 在几毫秒后被调用并锁定互斥锁,冻结线程 func 1 和 2 正在运行。
  • 现在 func 1 卡在中途并且线程被冻结,所以 func 1 永远不会完成并且互斥锁被永远锁定,等待 func 1 完成。

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

boost::mutex g_Mutex;
lua_State* L;

// Function 1 is called from some other thread
void FunctionOne()
{
    g_Mutex.lock();

    lua_performcalc(L);

    g_Mutex.unlock();
}

// Function 2 is called from some other thread a few ms later, freezing the thread
// and Function 1 never finishes
void FunctionTwo()
{
    g_Mutex.lock();

    lua_performothercalc(L);

    g_Mutex.unlock();
}
4

2 回答 2

8

这些函数是否旨在可重入,以便 FunctionOne 在持有互斥锁的同时调用自身或 FunctionTwo?反之亦然,FunctionTwo 锁定互斥锁,然后在互斥锁被锁定时调用 FunctionOne/FunctionTwo?

  • 如果不是,那么您不应该从同一个线程调用这两个函数。如果您打算将 FunctionTwo 阻塞直到 FunctionOne 完成,那么在同一个线程上调用它是错误的。如果 lua_performcalc 最终调用 FunctionTwo,就会发生这种情况。这是在同一线程上调用它们的唯一方法。

  • 如果是这样,那么您需要一个recursive_mutex。一个普通的互斥锁只能被锁定一次;从同一个线程再次锁定它是一个错误。一个递归互斥锁可以被单个线程多次锁定,并且一直被锁定直到线程调用解锁相同次数。

在任何一种情况下,您都应该避免显式调用 lock 和 unlock。如果抛出异常,互斥锁将不会被解锁。最好使用 RAII 样式的锁定,如下所示:

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

    ...critical section code...

    // mutex is unlocked when 'lock' goes out of scope
}
于 2012-12-10T17:46:22.530 回答
3

你的描述不正确。互斥锁不能被锁定两次。你有一个不同的问题。

  • 在互斥锁被锁定时检查重入。
  • 检查异常

避免出现您应该使用的异常问题boost::mutex::scoped_lock( RAAI )

于 2012-12-10T17:59:41.777 回答