使用 InterlockedCompareExchange 无锁
我正在尝试使用互锁操作使以下代码片段无锁,知道如何翻译吗?
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();
}
这里面有什么问题/种族吗?
I am trying to make following snip of code lockless using interlocked operations, Any idea how to translate this?
if (m_Ref == 0xFFFF)
m_Ref = 1;
else
{
if (++m_Ref == 1)
CallSomething(); //
}
I was thinking something like
if (InterlockedCompareExchange(&m_Ref, 1, 0xFFFF) != 0xFFFF))
{
if (InterlockedIncrement(&m_Ref) == 1)
CallSomething();
}
Is there any issues/race in this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从表面上看,这看起来是正确的,但每次连续使用两个互锁操作时,您都会将自己暴露在 ABA 问题。在这种情况下,一个线程无法将其从 0xFFFF 更改为 1(ICX 返回
!=0xFFFF
),因此它会继续执行if
分支并递增它。在运行InterlockedIncrement
之前,另一个线程将m_ref
更改回 0xFFFF,并且原始线程递增 0xFFFF。根据 m_ref 的类型/语义,效果会很谨慎,但肯定会很糟糕。您应该对 0xFFF 到 1 以及 X 到 X+1 执行一次 ICX 操作,并且如果丢失 ICX,请务必重试:
This looks correct at a superficial glance, but every time you use two interlocked operations in a row you are exposing yourself to the ABA problem. In this case one thread fail to change it from 0xFFFF to 1 (the ICX returns
!=0xFFFF
) so it goes ahead and takes theif
branch and increments it. Before it runs theInterlockedIncrement
another threads changes them_ref
back to 0xFFFF and the original thread increments 0xFFFF. Depending on the type/semantics of m_ref the effect will wary, but will surely be bad.You should do one single ICX operation, for both the 0xFFF to 1 and X to X+1, and always retry if you lost the ICX:
是的,有一场比赛。另一个上下文可以在 InterlockedCompareExchange 和 InterlockedIncrement 之间做很多事情
Yes there's a race. Another context could do a lot in between
InterlockedCompareExchange
andInterlockedIncrement