8

我在某处读到互斥锁的开销并不多,因为上下文切换仅在争用情况下发生。

在 Linux 中也称为 Futex。

同样的事情在 Windows 中也适用吗?关键部分是否更适合 Linux 中的互斥锁。

从我收集的信息来看,与互斥锁相比,关键部分提供了更好的最佳性能,这对每种情况都是如此吗?

是否存在互斥锁比 Windows 中的关键部分更快的极端情况。

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

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

4

2 回答 2

13

考虑到具体目的,Critical SectionsMutexes认为您不能就成本提出问题,因为当您需要多个线程接触相同数据时,您没有太多选择。显然,如果你只需要增加/减少一个数字,你可以使用数字Interlocked*()上的函数volatile,你很高兴。但是对于更复杂的事情,您需要使用同步对象。

从这里开始阅读Windows^ 上可用的同步对象。所有功能都列在那里,很好地分组并正确解释。有些仅适用于 Windows 8。

至于你的问题,Critical SectionsMutexes 更便宜,因为它们被设计为在相同的过程中运行。阅读这个^这个^或只是下面的报价。

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

Critical Sections用于相同的进程同步和Mutexes跨进程同步。 只有当我真的需要知道同步对象是否被放弃时,我才会在同一进程中使用互斥锁。

因此,如果您需要一个同步对象,问题不在于成本是多少,而在于哪个更便宜:) 除了内存损坏之外别无选择。

PS:可能有像这里所选答案中提到的那样的替代方案^但我总是选择特定于核心平台的功能与跨平台性。它总是更快!因此,如果您使用 Windows,请使用 Windows 的工具 :)

更新

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

愚蠢的例子获取一个 URL 列表。你需要抓取它们并分析它们。

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

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

PS:我只考虑 URL :)

更新 2:

需要在项目中进行一些测量。结果非常令人惊讶:

  • Astd::mutex最贵。(跨平台的代价)
  • Windows 本Mutex机比std.
  • ACritical SectionnativeMutex快 2 倍。
  • ASlimReadWriteLock是 的 +-10% Critical Section
  • 我自制的InterlockedMutex(自旋锁)Critical Section.
于 2013-08-06T23:35:35.157 回答
1

在 Windows 8 上使用 std::mutex 我通常通过使用我自己定制的自旋锁获得 3-4 倍的改进(在非竞争情况下)加速:

基于互斥锁

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 上使用什么下划线,因为它会生成很多代码。

于 2013-12-05T10:30:48.747 回答