C++ 使用联锁比较交换的无锁

C++ 使用联锁比较交换的无锁,c++,multithreading,synchronization,interlocked,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)

我正在尝试使用联锁操作来实现以下代码的无锁剪切,你知道如何翻译吗

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

这有什么问题/竞争吗?

是的,有竞争。另一个上下文可以在
InterlocatedCompareExchange
InterlocatedIncrement

之间做很多事情,乍一看这看起来是正确的,但每次在一行中使用两个互锁操作时,您都会暴露自己。在这种情况下,一个线程无法将其从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 ();
}
volatile m_ref;
ref,newRef,icxref;
做
{
ref=m_ref;
newRef=(0xFFFF==ref)?1:++ref;
icxref=联锁比较交换(&m_ref,newRef,ref);
}while(icxref!=ref);
if(newRef==1&&ref!=0xFFFF)
{
DoSomething();
}

谢谢,我也这么想,你知道怎么解决这个问题吗?@Suresh:不知道,如果你想不上锁的话。如果您可以更改为允许0,则在
InterlockedIncrement
@Suresh的返回值上使用
%
。@如果您不希望在实际运行的代码中出现太多竞争,那么您可以使用InterlockedCompareeExchange作为一种乐观的锁定机制。@Remus Rusanu-谢谢,这非常完美sense@GMan:内存映射需要什么如何处理volatile?@Remus:这是volatile的唯一用途,它可以观察到对它的读写行为,与多线程无关。您使用它作为
InterlocatedCompareeExchange
的参数已经提供了可观察的行为。@Gman:
ref=m\u ref?没有volatile decorator,它没有获取语义。@Remus:它没有volatile的语法。。。无论如何,编译器无法省略该赋值,因为它将在以后的库调用中使用。(即,它具有可观察的行为。)