我有一些多线程代码(请参阅问题Windows API Thread Pool simple example),我正在使用计数器来识别线程。
我被建议使用InterlockedIncrement在线程的回调函数中递增此计数器。然而,这似乎没有正确锁定变量,因为我遇到了一些并发问题。我通过手动使用临界区替换了InterlockedIncrement:EnterCriticalSection / counter ++ / LeaveCriticalSection,现在可以完美地运行。
为什么会这样? Aren这两个选项应该严格等同吗? 请注意,我所说的只是启动一对(大约10个)线程。
答案 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
返回唯一递增的值。如果要查看唯一值,则需要在计算中使用该值。