1

我有一个应用程序,其中几个线程共享一个互斥锁。

std::lock_guard< std::recursive_mutex > lock(globalMutex_);

一个密集(T1)其他较小(T2,T3..)。我有一个例子,其中需要锁的线程在成功获取锁之前经常被阻塞 100 秒。

获取锁的线程(T1 so)通常以以下方式进行:

void func()
{
  std::lock_guard< std::recursive_mutex > lock(globalMutex_);
  processing();
}

globalMutex_然后定期释放。

奇怪的行为:

T1在总共 100 秒的时间内系统地获得了锁,而其他线程根本没有获得锁

(在其他线程中,我有相同的模式,但其他函数的调用频率较低)

问题: 有什么可以解释的?这是正常行为吗?

上下文: 我在 Windows 10 / 最新版本的 Visual Studio / 64 位 / GUI 应用程序下

注意: 即使我把T2放在了高优先级,情况也是一样的。

4

3 回答 3

2

std::mutex不保证互斥锁按线程调用的顺序锁定lock()。当一个线程释放锁时,如果线程快速重新锁定锁,那么除非另一个线程已经在等待锁并且正在同时执行第一个线程很可能成功地重新获得锁。

最简单的解决方案是保持锁的时间尽可能短,并尝试确保每个线程至少花费一段时间没有锁定互斥锁。

更复杂的解决方案是创建自己的互斥锁类,它确实提供了一些关于锁定/解锁顺序的保证。std::mutex您可以使用和的组合来实现这一点std::condition_variable

于 2018-06-14T14:48:12.800 回答
1

这看起来像一个错误:

{
  std::lock_guard< std::recursive_mutex > lock(globalMutex_);
  processing();
}

做什么processing()?如果花费的时间超过几微秒,那么可能有一种更有效的方法来解决您的问题。有时它看起来像这样:

bool success=false;
while (! success) {
    auto result = speculative_processing();
    {
        std::lock_guard< std::recursive_mutex > lock(globalMutex_);
        success = attempt_to_publish(result);
    }
}

通常情况下,多线程程序中的各个线程必须做额外的工作才能避免相互干扰。但是通过相互避开,他们能够更好地利用多个处理器,并且他们可以更快地完成整个工作。

于 2018-06-14T15:48:33.490 回答
0

您将使用 condition_variable 实现您的目标。

std::condition_variable cv;
bool busy = false;
void func()
{
  {
    std::unique_lock<std::mutex> lk(globalMutex_);
    cv.wait(lk, []{return !busy;});
    busy = true;
  }
  processing();
  busy = false;
  cv.notify_one();
}
于 2020-01-14T16:19:29.907 回答