windows InterlockedIncrement vs EnterCriticalSection/counter++/LeaveCriticalSection

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8393990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:36:06  来源:igfitidea点击:

InterlockedIncrement vs EnterCriticalSection/counter++/LeaveCriticalSection

c++windowsmultithreadingthread-safety

提问by nbonneel

I have some multithreaded code (see question Windows API Thread Pool simple example) for which I am using a counter to identify a thread.

我有一些多线程代码(请参阅问题Windows API 线程池简单示例),我使用计数器来识别线程。

I have been advised to use an InterlockedIncrement to increment this counter in the thread's callback function. However this didn't seem to properly lock the variable, as I encountered some concurrency issues. I replaced the InterlockedIncrement by using a critical section manually : EnterCriticalSection/counter++/LeaveCriticalSection and this now works perfectly.

我被建议使用 InterlockedIncrement 来增加线程回调函数中的这个计数器。但是,这似乎没有正确锁定变量,因为我遇到了一些并发问题。我通过手动使用临界区替换了 InterlockedIncrement:EnterCriticalSection/counter++/LeaveCriticalSection,现在它可以完美运行。

Why is it so ? Aren't the two options supposed to be strictly equivalent ? Note that I am talking about launching just a couple (about 10) of threads.

为什么会这样?这两个选项不应该严格等效吗?请注意,我说的是只启动几个(大约 10 个)线程。

回答by Raymond Chen

Your code is not using InterlockedIncrementcorrectly.

您的代码未InterlockedIncrement正确使用。

InterlockedIncrement(&(thread.threadCount)); 
DWORD tid = (thread.threadCount-1)%thread.size(); 

This performs an atomic increment of thread.threadCount, but instead of saving the atomically-incremented value, you ignore it and go back to the thread.threadCountvariable (which may have been incremented by another thread in the meantime).

这将执行 的原子增量thread.threadCount,但不是保存原子增量的值,而是忽略它并返回到thread.threadCount变量(在此期间它可能已被另一个线程增量)。

In your case, what happens is that two threads did an InterlockedIncrementnearly simultaneously, incrementing it from 1 to 2, then 2 to 3. Both threads then read thread.threadCountand got 3 back (then subtracted 1 to get a final result of 2).

在您的情况下,发生的情况是两个线程InterlockedIncrement几乎同时执行,将其从 1 增加到 2,然后从 2 增加到 3。然后两个线程都读取thread.threadCount并返回 3(然后减去 1 得到 2 的最终结果)。

The correct code is

正确的代码是

LONG tidUnique = InterlockedIncrement(&(thread.threadCount));
DWORD tid = (tidUnique-1)%thread.size(); 

The unique incremented value is returned by InterlockedIncrement. You need to use that value in your computations if you want to see the unique value.

唯一的递增值由 返回InterlockedIncrement。如果您想查看唯一值,则需要在计算中使用该值。