如何在C#中自动交换2个int?
什么(如果有的话)是x86 asm xchg
指令的C#等价物?
有了这个命令,哪个imo是一个真正的交换(与Interlocked.Exchange
不同),我可以简单地primefaces交换两个int,这就是我真正想做的事情。
更新:
示例代码基于我的建议。 变量后缀“_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 (ie 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(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;
请注意延迟更新。
这是一个奇怪的想法。 我不知道您是如何设置数据结构的。 但是如果有可能你可以将你的两个int
值存储long
,那么我认为你可以primefaces地交换它们。
例如,假设您按以下方式包装了两个值:
class SwappablePair { long m_pair; public SwappablePair(int x, int y) { m_pair = ((long)x << 32) | (uint)y; } /// /// Reads the values of X and Y atomically. /// public void GetValues(out int x, out int y) { long current = Interlocked.Read(ref m_pair); x = (int)(current >> 32); y = (int)(current & 0xffffffff); } /// /// Sets the values of X and Y atomically. /// public void SetValues(int x, int y) { // If you wanted, you could also take the return value here // and set two out int parameters to indicate what the previous // values were. Interlocked.Exchange(ref m_pair, ((long)x << 32) | (uint)y); } }
然后你似乎可以添加以下Swap
方法来“primefaces地”产生交换对(实际上,我不知道是否公平地说下面是primefaces的;它更像是产生与primefaces相同的结果交换 )。
/// /// Swaps the values of X and Y atomically. /// public void Swap() { long orig, swapped; do { orig = Interlocked.Read(ref m_pair); swapped = orig << 32 | (uint)(orig >> 32); } while (Interlocked.CompareExchange(ref m_pair, swapped, orig) != orig); }
当然,我很可能错误地实现了这一点。 这个想法可能存在缺陷。 这只是一个想法。
这是CLR中Interlocked.Exchange()的可能实现,从SSCLI20源复制:
请注意,函数名称中的UP表示UniProcessor。 这在SMP /多核系统上不是primefaces的。 此实现仅供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
前缀,因此与xadd
或cmpxchg
不同,单核系统仍然无法省略它仍然在一条指令中执行操作,使其在中断方面成为primefaces(因此在单处理器上的其他线程)。
奇怪的跳跃代码是在分支预测数据不可用的情况下的优化。 毋庸置疑,尝试做得比一些非常优秀的软件工程师在芯片制造商提供慷慨帮助的情况下做得更好的工作是一项艰巨的任务。
为什么Interlocked.Exchange
不适合你?
如果您需要交换确切的内存位置,那么您使用了错误的语言和平台,因为.NET将内存管理抽象出去,因此您无需考虑它。
如果你必须在没有Interlocked.Exchange
情况下做这样的事情,你可以编写一些标记为unsafe
代码,并像在C或C ++中那样进行传统的基于指针的交换,但是你需要将它包装在合适的同步环境中,这样这是一个primefaces操作。
更新
您不需要求助于unsafe
代码以primefaces方式进行交换。 您可以将代码包装在同步上下文中以使其成为primefaces。
lock (myLockObject) { var x = Interlocked.Exchange(a, b); Interlocked.Exchange(b, x); }
更新2
如果同步不是一个选项(如评论中所示),那么我相信你运气不好。 当你追逐一些无法衡量的效率时,你可能想集中精力去其他地方。 如果交换两个整数值是一个巨大的性能,你可能使用了错误的平台。
Interlocked.Exchange是你唯一可以做的事情:
var x = Interlocked.Exchange(a, b); Interlocked.Exchange(b, x);
你是正确的,这不是primefaces的,但是使用局部变量,只要两行执行,就可以保证值是一致的。 您的其他选项是不安全的代码(用于使用指针),使用p / invoke到本机库,或重新设计以便不再需要它。
根据MSDN ,Interlocked.Exchange 是primefaces的。
如果它不适合您,您可以使用C / C ++在不安全的部分中实现XCHG。
Interlocked.Exchange是在c#中以线程安全方式交换两个int值的最佳方法。
使用这个类,即使您有多处理器计算机,也不知道您的线程将在哪个处理器中运行。
我想我刚刚找到了最好的解决方案。 它是:
Interlocked.Exchange()方法(ref T,T)
所有“新”变量都可以在类(Of T)中设置,并与当前变量交换。 这样可以实现primefaces快照,同时有效地交换任意数量的变量。
在Interlocked.Exchange之外,我假设XCHG命令可能是XOR Swap的一个实现,所以你可以编写自己的。
C语法:(来自维基百科链接)
void xorSwap (int *x, int *y) { if (x != y) { *x ^= *y; *y ^= *x; *x ^= *y; } }
编辑这不是primefaces的,你必须自己同步它