在Windows上互斥、关键部分等的成本

Cost of mutex,critical section etc on Windows

本文关键字:键部 Windows      更新时间:2023-10-16

我在某个地方读到互斥的开销并不大,因为上下文切换只在争用的情况下发生。

Linux中也称为Futex。

同样的东西在Windows中适用吗?Critical Section是Linux中更适合互斥的映射吗。

根据我所收集的信息,与Mutex相比,Critical Sections提供了更好的最佳性能,这在所有情况下都是真的吗?

在Windows中,是否存在互斥量比关键部分快的情况。

假设只有一个进程线程正在访问互斥对象(只是为了消除关键部分的其他好处)

添加信息:操作系统windows服务器,
语言C++

考虑到Critical SectionsMutexes的特定用途,我认为您不能问关于成本的问题,因为当您需要多个线程处理相同的数据时,您没有太多选择。显然,如果您只需要增加/减少一个数字,您可以在volatile数字上使用Interlocked*()函数,这样就可以了。但对于任何更复杂的情况,都需要使用同步对象。

从这里开始阅读Windows^上可用的同步对象。所有功能都列在那里,很好地分组并进行了适当的解释有些只是Windows 8

关于您的问题,Critical SectionsMutexe便宜,因为它们设计用于在相同的过程中操作阅读这个^和这个^,或者只阅读下面的引文。

关键部分对象提供与互斥对象类似的同步,只是关键部分只能由单个进程的线程使用。事件、互斥对象和信号量对象也可以在单个进程应用程序中使用,但关键部分对象为互斥同步(特定于处理器的测试和设置指令)提供了一种稍微更快、更高效的机制。与互斥对象一样,关键部分对象一次只能由一个线程拥有,这对于保护共享资源免受同时访问非常有用。与互斥对象不同,无法判断关键部分是否已被放弃。

我使用Critical Sections进行同进程同步,使用Mutexes进行跨进程同步 只有当我真的需要知道同步对象是否被放弃时,我才会在同一过程中使用Mutex

所以,如果你需要一个同步对象,问题不是成本是多少,而是哪个更便宜:)除了内存损坏,别无选择

PS:可能有其他选择,比如这里选择的答案中提到的,但我总是选择核心平台特定功能与跨平台。它总是更快因此,如果您使用Windows,请使用Windows的工具:)

更新

根据您的需要,您可以通过尝试在线程中尽可能多地执行自包含的工作来减少同步对象的需要,并且只在最后或不时地组合数据。

愚蠢的例子获取URL列表。你需要搜集并分析它们

  1. 加入一堆线程,开始从输入列表中一个接一个地选择URL。对于你的每一个过程,你都会在进行过程中集中结果。这是实时的,很酷
  2. 或者,您可以在每个线程中放入一个输入URL片段。这样就不需要同步选择过程。您将分析结果存储在线程中,最后只需组合一次结果。或者说,每10个URL就有一次。不是为他们每个人。这将大大减少同步操作

因此,可以通过选择正确的工具并思考如何降低锁定和解锁来降低成本。但成本无法去除:)

PS:我只在URL中思考:)

更新2:

有必要在一个项目中做一些测量。结果非常令人惊讶:

  • std::mutex是最昂贵的(跨平台价格)
  • Windows本机Mutexstd快2倍
  • Critical Section原生Mutex快2倍
  • SlimReadWriteLockCritical Section的+-10%
  • 我自制的InterlockedMutex(spinlock)Critical Section快1.25倍-1.75倍

在windows 8上使用std::mutex,通过使用我自己定制的旋转锁,我通常可以获得3-4x的改进(在非竞争情况下)

基于互斥的

auto time = TimeIt([&]() {
for (int i = 0; i < tries; i++) {
    bool val = mutex.try_lock();
    if (val) {
        data.value = 1;
    }
}

});

国产免锁

time = TimeIt([&]() {
    for (int i = 0; i < tries; i++) {
        if (!guard.exchange(true)) {
            // I own you
            data.value = 1;
            guard.store(true);
        }
    }
});

测试是在x86上进行的。

我还没有弄清楚std::mutex在windows上使用下划线是什么,因为它生成了很多代码。