gpt4 book ai didi

multithreading - 退出临界区

转载 作者:行者123 更新时间:2023-12-02 02:54:34 25 4
gpt4 key购买 nike

考虑多个线程并发执行以下代码:

long gf = 0;// global variable or class member

//...

if (InterlockedCompareExchange(&gf, 1, 0)==0) // lock cmpxchg
{
// some exclusive code - must not execute in concurrent
gf = 0; // this is ok ? or need
//InterlockedExchange(&gf, 0); // [lock] xchg
}

将上面的代码视为类似 C 的伪代码,这些代码将或多或少地直接转换为汇编,而无需对编译器优化(例如重新排序和存储消除)做出通常的让步。

因此,在某些线程独占获取标志 gf 之后 - 退出临界区是否足以写入一个零(如 gf = 0 中)或者这是否需要互锁 - InterlockedExchange(&gf, 0)?

如果两者都正常,假设多个内核同时调用 InterlockedCompareExchange(&gf, 1, 0) 的可能性很高,从性能角度来看哪个更好?

多个线程周期性地执行此代码(从几个地方,当某些事件触发时),重要的是下一个线程在释放后尽快再次进入临界区。

最佳答案

相关:Spinlock with XCHG解释为什么你不需要需要xchg释放 x86 asm 中的锁,只需一条存储指令。

但是在 C++ 中,您需要比普通 gf = 0; 更强大的东西在平原上 long gf变量。C/C++ 内存模型(对于普通变量)是非常弱排序的,即使在针对强排序的 x86 进行编译时也是如此,因为这对于优化至关重要。

您需要一个释放存储来正确释放锁,不允许临界区中的操作通过在编译时或运行时使用 gf=0 重新排序而泄漏出临界区。店铺。 http://preshing.com/20120913/acquire-and-release-semantics/ .

由于您使用的是 long gf , 不是 volatile long gf ,并且您没有使用编译器内存屏障,您的代码中没有任何内容可以阻止编译时重新排序。 (x86 asm 存储具有发布语义,因此我们需要担心的只是编译时重新排序。)http://preshing.com/20120625/memory-ordering-at-compile-time/


我们使用 std::atomic<long> gf; 尽可能便宜地获得我们需要的一切和 gf.store(0, std::memory_order_release); atomic<long>在支持 InterlockedExchange 的每个平台上都是无锁的, AFAIK,所以你应该可以混合搭配。 (或者只使用 gf.exchange() 获取锁。如果滚动你自己的锁,请记住你应该在只读操作上循环 + _mm_pause() 在等待锁时,不要用 xchg 敲打或 lock cmpxchg 并可能延迟解锁。请参阅 Locks around memory manipulation via inline assembly

这是 Why is integer assignment on a naturally aligned variable atomic on x86? 中警告的情况之一。你需要的 atomic<>确保编译器实际在您需要的地方/时间进行存储。

关于multithreading - 退出临界区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50221295/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com