C++ Boost是否支持Windows EnterCriticalSection API?

C++ Boost是否支持Windows EnterCriticalSection API?,c++,windows,boost,critical-section,C++,Windows,Boost,Critical Section,我知道Boost支持互斥锁和锁护,可以用来实现关键部分 但是Windows有一个用于关键部分的特殊API(请参阅和),它比互斥锁(用于很少争用的短代码部分)快得多 因此,我的问题是——在Boost中,有可能利用这个API,并在其他平台上回退到基于spinlock/mutex/futex的实现吗?简单的答案是否定的 以下是一些相关背景 顺便说一句,我同意互斥是一种更通用的解决方案 从性能的角度来看。但公平地说,简单来说,CS更快 设计。我认为,支持他们的可能性应该是最大的 最少 考虑到 这就是有人

我知道Boost支持互斥锁和锁护,可以用来实现关键部分

但是Windows有一个用于关键部分的特殊API(请参阅和),它比互斥锁(用于很少争用的短代码部分)快得多


因此,我的问题是——在Boost中,有可能利用这个API,并在其他平台上回退到基于spinlock/mutex/futex的实现吗?

简单的答案是否定的

以下是一些相关背景

顺便说一句,我同意互斥是一种更通用的解决方案

从性能的角度来看。但公平地说,简单来说,CS更快 设计。我认为,支持他们的可能性应该是最大的 最少 考虑到

这就是有人指给我看的那篇文章。结论是 只有在以下情况下,CS才会更快:

  • 进程中总共少于8个线程
  • 你不是在后台跑步
  • 你不是在双处理器机器上
对我来说,这意味着简单的测试可以产生良好的CS性能 结果,但任何现实世界的计划都最好有一个全面的计划 互斥

我并不反对支持CS实现。然而,我 最初选择不这样做的原因如下:

  • 使用PIMPL可以获得构造和破坏命中 或者您必须在Boost.Threads标题中包含Windows.h, 这是我根本不想做的。(这可以通过以下方式解决: 从MSDN模拟CS ala OPTEX。)
  • 根据这篇研究论文,大多数项目不会从中受益 一个CS设计
  • 编写一个(不可移植的)关键的_节类是很简单的 如果你真的能利用它,就遵循互斥模型
现在我认为我已经做出了正确的选择,尽管在这条路上我们 可能会将实施更改为使用关键部分或OPTEX

比尔·坎普夫


作为一个帮助维护Boost.Thread的人,以及一个未能将事件对象添加到Boost.Thread中的人,我认为关键部分从未添加过,也不会添加到Boost中,原因如下:

  • 使用boost::atomic和boost::condition_变量构建Win32 critical section非常简单,因此不值得正式使用。这里可能是你能想象到的最复杂的一个,但是非常可配置,包括准备好constexpr(不要问!)

    您可以通过匹配(基本)可锁定概念,使用原子比较交换(非x86/x64)或原子交换(x86/x64),然后在关键部分使用锁保护来获取它,从而构建您自己的

    有些人可能会反对win32关键部分不是这个。恐怕是这样的:它只是在一个原子上旋转一个旋转计数,然后懒洋洋地尝试分配一个win32事件对象,然后等待它。没什么特别的

  • 尽管您可能认为关键部分(真正的用户模式互斥)更好/更快/什么的,但它们可能没有您想象的那么好。在Windows内部使用win32信号量作为内核等待对象时,互斥是一个巨大而沉重的东西,因为需要模拟线程取消,并在通用环境中表现良好。对于某些单一用例,编写一个比另一个更快的并发结构是非常容易的,但是编写一个并发结构是非常非常困难的,它包括:

  • 在无争议的情况下,比标准实现更快
  • 在竞争激烈的情况下,比标准实现更快
  • 在激烈竞争的情况下,比标准实现更快
  • 即使你管理了以上三种情况,这仍然是不够的:你还需要对最坏情况下的进程排序做出一些保证,以确定锁定、等待和解锁的特定模式是否会产生可预测的结果。这就是为什么线程工具在狭窄的用例场景中看起来很慢的原因,所以Boost.Thread就像STL一样,在非争用的用例中看起来比手动锁定代码慢得多

  • 线程已经在用户模式下做了大量工作,以避免在Windows上进入内核休眠。在POSIX上,任何主要的pthreads实现都会做大量的工作来避免内核休眠,因此Boost.Thread不会复制这项工作。换句话说,关键部分在扩展到负载行为方面不会给你带来任何好处,尽管它不可避免地会提升。线程v4(尤其是在Windows上)会做大量的工作,而一个简单的实现却不会(计划中的Boost重写。线程在Windows上的效率要高得多,因为它可以假设Windows Vista或更高版本)


  • 因此,看起来默认的Boost互斥体不支持它,但是
    asio::detail::mutex
    支持它

    所以我最后用了这个:

    #include <boost/asio/detail/mutex.hpp>
    #include <boost/thread.hpp>
    
    using boost::asio::detail::mutex;
    using boost::lock_guard;
    
    int myFunc()
    {
      static mutex mtx;
      lock_guard<mutex> lock(mtx);
      . . .
    }
    
    #包括
    #包括
    使用boost::asio::detail::mutex;
    使用boost::lock_-guard;
    int myFunc()
    {
    静态互斥;
    锁和防护锁(mtx);
    . . .
    }
    
    Mmm。有人指出它可能使用互斥,而不是CriticalSection。在我得出结论之前,让我再看一看,在Windows中,关键部分不是互斥。它是一个用户模式的对象,而互斥是一个内核模式的对象。显然,这个实现细节在Boost线程的历史中已经发生了变化。我只能假设这是有充分理由的。我建议你自己写一个基本的时钟模型——一个可能在地球上浮动webs@rustyx我知道这一点。我想强调的是,尽管
    boost::mutex
    被命名为“mutex”,但这并不一定意味着实现使用了同名的Win32原语。(尽管,所有这些现在还没有定论)更新了我的答案,使之更具相关性