锁通过一个线程保持太长时间

时间:2018-06-14 14:34:15

标签: c++ multithreading mutex starvation

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

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秒的时间内系统地获取锁定,而另一个线程根本没有获得锁定

(在其他线程中我有相同的模式,但另一个func被不常调用)

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

上下文: 我是windows 10 /最新版本的visual studio / 64位/ GUI应用程序

注意:的 即使我将 T2 置于高优先级,情况也是如此。

3 个答案:

答案 0 :(得分:2)

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

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

更复杂的解决方案是创建自己的互斥类,它确实提供了有关锁定/解锁顺序的一些保证。您可以结合使用std::mutexstd::condition_variable来实现此目标。

答案 1 :(得分: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);
    }
}

通常情况下,多线程程序中的各个线程必须做额外的工作才能避开彼此的方式。但是,通过彼此保持一致,他们能够更好地利用多个处理器,并且他们可以更快地完成整个工作。

答案 2 :(得分: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();
}
相关问题