繁体   English   中英

Interlocked.Exchange澄清

[英]Interlocked.Exchange clarification

我有一些简单(希望)的问题,我一直无法找到答案 -

假设我有多个线程可以访问的对象a,b。

Interlocked.Exchange(ref a, b)

如果'b'不是易变的,这个操作会不会这样处理? 即它会从内存中获取此变量的最新值吗? 如果是这样,那写入是'原子'吗? 据我所知,Interlocked.Exchange的主要目的是使用新写入将原来的'a'值作为原子操作。 但我的主要困惑在于'b'实际写入'a'的价值。

我的第二个问题与本文中的引用有关:

http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

“一个有趣的观点是C#中的所有写操作都是根据本文和此处记录的内存模型进行的,并且也可能是这样实现的.C#语言的ECMA规范实际上定义了一个较弱的模型,其中写入默认情况下不是易失性的“。

这是真的? 如果是这样,如果不关心'a'的先前值,是否有Interlocked.Exchange的目的? (与我的第一个例子有关)。 我没有在StackOverflow上看到任何关于每个写入易失性的文章或评论。 但是,我知道写入是原子的。

编辑:如果我的第一个问题的答案是“b”不被视为易失性,而我的第二个问题的答案是写入确实是不稳定的,那么跟进就是,什么时候是联锁的。如果我们不这样做,则有用关心'a'的先前价值?

传递给Exchange的变量(或传递给任何方法的任何volatile变量)在传递时不会保留“volatile”...实际上不需要它是volatile (在方法调用期间)因为唯一的volatile确保编译器不优化变量的使用(这通常意味着优化写入寄存器,因此值只能由单个处理器“看到”)。 在x86 / x64以外的处理器上,这有时意味着保证获取或释放语义的指令。 .NET不使用寄存器进行参数传递,因此volatile不会影响传递的参数的“波动性”。 由于内存模型的可见性保证,它必须始终从内存中获取最新值

RE问题2:引用是“真实的”,取决于字段的声明,有可见性保证wrt字段; 但是没有“volatile”字段访问可以在某些使用阶段被优化到寄存器中,可能隐藏来自其他处理器的某些写入。

Interlocked交换使非原子的操作看起来是原子的。 交换本质上类似于:

var x = someVariable;
someVariable = y;

无论someVariable的类型如何,这都不可能是原子的。 Exchange使此操作成为原子。 这也是非原子类型的原子,如doublelong (32位)等。

Exchange使用这个原子的部分原因是使用内存栅栏 - 这使得写入可见而不是重新排序,并且在内存栅栏之后的指令序列中读取相同的内存地址。

如果您不关心“a”的先前值,为什么要使用Exchange 如果你不关心实际的“交换”,那么VolatileWrite似乎更合适。

或者,如果不需要“交换”,您可以编写线程安全代码来模拟“A = B”,如下所示:

Thread.MemoryBarrier();
A=B;

FWIW, Interlocked部分模拟了某些处理器中的比较和交换(CAS)指令。 这些指令允许您在一条指令中执行这两项操作(使其成为原子)。 如果没有像Interlocked这样的东西,编译器可能很难推断出应该使用这些CAS指令之一。 此外, Interlocked在不支持这些CAS指令的处理器上提供原子使用(以及其他可能非原子指令,如inc和dec - 可能并非在所有处理器上都可用)

如果'b'不是易变的,这个操作会不会这样处理?

b是共享变量时,我认为你不应该使用它。 这样就消除了整个问题。 但Exchange总会使用Memorybarrier,所以答案可能是肯定的。

何时是interlocked.exhange有用,如果我们不关心'a'的先前值?

double的重载非常有用,因为写入double不是原子的。 32位系统上的Int64也是如此。

但是对于原子类型的Exchange()重载,用例不太清楚。 我认为大多数算法都支持CompareExcange()

所以考虑一下原子Write()。

如果'b'不是易变的,这个操作会不会这样处理?

是的,因为根据这个来源Interlocked类的所有方法都会生成隐式内存栅栏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM