使用InterlockedCompareExchange无锁

时间:2011-05-02 22:38:34

标签: c++ multithreading synchronization interlocked

我正在尝试使用互锁操作使代码片段无锁,任何想法如何翻译?

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();
}

这有什么问题/竞争吗?

2 个答案:

答案 0 :(得分:8)

从表面上看,这看起来是正确的,但每次连续使用两个互锁操作时,您都会将自己暴露给ABA problem。在这种情况下,一个线程无法将其从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 ();
}

答案 1 :(得分:4)

是的,这是一场比赛。另一个上下文可以在InterlockedCompareExchangeInterlockedIncrement

之间做很多事情