【问题标题】:Leads a C++11 std::mutex lock the blocked thread into a passive wait state?导致 C++11 std::mutex 将阻塞线程锁定为被动等待状态?
【发布时间】:2015-10-05 14:06:57
【问题描述】:

我有以下情况:

两个 C++11 线程正在进行计算,它们通过 std::mutex 同步。

线程 A 锁定互斥体,直到数据为线程 B 执行的操作做好准备。当互斥锁被解锁时,线程 B 开始工作。

线程 B 尝试锁定互斥体并被阻塞,直到被线程 A 解锁。

void ThreadA (std::mutex* mtx, char* data)
{
    mtx->lock();
    //do something useful with data
    mtx->unlock();
}

void ThreadB (std::mutex* mtx, char* data)
{
    mtx->lock(); //wait until Thread A is ready
    //do something useful with data
    //.....
}

断言线程A可以先阻塞互斥体。

现在我想知道线程 B 中的 mtx->lock() 是等待主动还是被动。线程 B 轮询互斥体状态并浪费处理器时间或在互斥体解锁时被调度程序被动释放也是如此。

在不同的 C++ 参考文献中,只提到了线程被阻塞,但没有提到阻塞的方式。

但是,std::mutex 实现是否几乎不依赖于使用的平台和操作系统?

【问题讨论】:

  • 如果你想让线程 B 在线程 A 执行一些其他工作后做一些工作,你肯定想要一个std::condition_variable。另外,避免在代码中直接调用lock() 成员函数;更喜欢使用std::unique_lock<T>std::lock_guard<T>
  • 我知道这是一种标准的做法。提到的例子是一个相当综合的例子。我想知道的是这种等待条件的特征,而不用花几天时间阅读 C++ 标准论文。
  • 这将是您的标准库的实现者认为在您的平台上最好的任何内容。

标签: c++ multithreading c++11


【解决方案1】:

这是高度定义的实现,即使对于相同的编译器和操作系统

例如,在 VC++ 上,在 Visual Studio 2010 中,std::mutex 是用 Win32 CRITICAL_SECTION 实现的。 EnterCriticalSection(CRITICAL_SECTION*) 有一些不错的功能:首先它尝试通过迭代 一次又一次地锁定CRITICAL_SECTION。在指定的迭代次数后,它会进行内核调用,使线程进入睡眠状态,只有在释放锁并重新开始整个交易时才会再次唤醒。 在这种情况下,该机制会在进入睡眠之前一次又一次地轮询锁,然后控制切换到内核。

Visual Studio 2012 带有不同的实现。 std::mutex 是用 Win32 互斥锁实现的。 Win32 mutex 将控制权立即转移到内核。锁没有进行主动轮询。

您可以在答案中阅读有关实现开关的信息:std::mutex performance compared to win32 CRITICAL_SECTION

因此,未指定互斥锁如何获取锁。最好不要依赖这种行为。

ps。不要手动锁定互斥锁,请改用std::lock_guard。此外,您可能希望使用condition_variable 来获得更精细的同步控制方式。

【讨论】:

  • 首先感谢您的回答。这就是我一直在寻找的。正如我提到的,我知道锁防护装置的事情,但我想知道事情是如何运作的。你还知道一些关于 unixoid 系统的文档吗?
  • 我对其他文件不熟悉,抱歉。但通常在谷歌上搜索“XXX 在内部是如何工作的”会给出很好的答案
  • 好的,非常感谢。现在,我至少有更多关键字可供搜索,并且可以通过跟踪找到更多信息。
猜你喜欢
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-24
相关资源
最近更新 更多