c# - 如何在 C# 中以原子方式交换 2 个整数?

标签 c# .net atomic

什么(如果有的话)是 x86 asm 的 C# 等价物 xchg指令?

使用该命令,imo 是一个真正的交换(与 Interlocked.Exchange 不同),我可以简单地原子交换两个整数,这正是我真正想要做的。

更新:

基于我的建议的示例代码。后缀为“_V”的变量被修饰为volatile:

// PART 3 - process links
// prepare the new Producer
address.ProducerNew.WorkMask_V = 0;
// copy the current LinkMask
address.ProducerNew.LinkMask_V = address.Producer.LinkMask_V;
// has another (any) thread indicated it dropped its message link from this thread?
if (this.routerEmptyMask[address.ID] != 0)
{
  // allow all other bits to remain on (i.e. turn off now defunct links)
  address.ProducerNew.LinkMask_V &= ~this.routerEmptyMask[address.ID];
  // reset
  this.routerEmptyMask[address.ID] = 0;
}
// PART 4 - swap
address.ProducerNew = Interlocked.Exchange<IPC.Producer>(ref address.Producer, address.ProducerNew);
// PART 5 - lazily include the new links, make a working copy
workMask = address.Producer.LinkMask_V |= address.ProducerNew.WorkMask_V;

注意惰性更新。

最佳答案

这是 CLR 中 Interlocked.Exchange() 的可能实现,从 SSCLI20 源代码复制而来:

请注意,函数名称中的 UP 表示 UniProcessor。这在 SMP/多核系统上不是原子的。此实现将仅由 CLR 在单核系统上使用。

FASTCALL_FUNC ExchangeUP,8
        _ASSERT_ALIGNED_4_X86 ecx
        mov     eax, [ecx]      ; attempted comparand
retry:
        cmpxchg [ecx], edx
        jne     retry1          ; predicted NOT taken
        retn
retry1:
        jmp     retry
FASTCALL_ENDFUNC ExchangeUP

它优于使用 XCHG,因为此代码无需总线锁定即可工作。 xchg 有一个隐含的 lock 前缀,所以与 xaddcmpxchg 不同,它不能被省略核心系统仍然在一条指令中执行操作,以使其相对于中断(以及单处理器上的其他线程)具有原子性。

奇怪的跳跃代码是在分支预测数据不可用的情况下进行的优化。毋庸置疑,在芯片制造商的慷慨帮助下,与非常优秀的软件工程师多年来深思熟虑的工作相比,试图做得更好是一项艰巨的任务。

关于c# - 如何在 C# 中以原子方式交换 2 个整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3855671/

相关文章:

.net - HashSet.Intersect() 的顺序对性能有影响吗?

c++ - 改进 InterlockedCompareExchange() 的原子读取

c# - try catch 不处理 BadImageFormatException

.net - VB.NET openFileDialog 崩溃

c# - 所有 .NET 程序集在 Windows Server 上运行都非常慢

.net - 在 .NET 中序列化数据传输对象

c++ - 为什么对象的初始化会调用复制构造函数?

c++ - shared_ptr 上的原子操作

c# - 如何链接调用,使用响应作为另一个调用的输入

c# - 找到多个 DbContext