5

我正在尝试使用联锁操作使以下代码片段无锁,知道如何翻译吗?

if (m_Ref == 0xFFFF)
    m_Ref = 1;
else
{
    if (++m_Ref == 1)
        CallSomething(); //

}

我在想类似的东西

if (InterlockedCompareExchange(&m_Ref, 1, 0xFFFF) != 0xFFFF))
{
    if (InterlockedIncrement(&m_Ref) == 1)
         CallSomething();
}

这有什么问题/种族吗?

4

2 回答 2

8

从表面上看,这看起来是正确的,但每次你连续使用两个互锁操作时,你都会将自己暴露在ABA 问题中。在这种情况下,一个线程未能将其从 0xFFFF 更改为 1(ICX 返回!=0xFFFF),因此它继续前进并采用if分支并递增它。在它运行之前,InterlockedIncrement另一个线程将其更改m_ref 回 0xFFFF 并且原始线程递增 0xFFFF。根据 m_ref 的类型/语义,效果会很谨慎,但肯定会很糟糕。

您应该对 0xFFF 到 1 和 X 到 X+1 执行一次 ICX 操作,如果丢失 ICX,请始终重试:

volatile <type> m_ref;

<type> ref, newRef, icxref;
do
{
   ref = m_ref;
   newRef = (0xFFFF == ref) ? 1 : ++ref;
   icxref = InterlockedCompareExchange (&m_ref, newRef, ref);
} while (icxref != ref);
if (newRef == 1 && ref != 0xFFFF)
{
   DoSomething ();
}
于 2011-05-02T22:53:27.023 回答
4

是的,有一场比赛。InterlockedCompareExchange另一个上下文可以在两者之间做很多事情InterlockedIncrement

于 2011-05-02T22:42:18.733 回答