InterlockedIncrement vs EnterCriticalSection / counter ++ / LeaveCriticalSection

时间:2011-12-06 00:52:12

标签: c++ windows multithreading thread-safety

我有一些多线程代码(请参阅问题Windows API Thread Pool simple example),我正在使用计数器来识别线程。

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

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

1 个答案:

答案 0 :(得分:27)

您的代码未正确使用InterlockedIncrement

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

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

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

正确的代码是

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

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