- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有几个简单的(希望是)问题,我一直无法找到答案 -
假设我有多个线程可以访问的对象 a、b。
Interlocked.Exchange(ref a, b)
如果“b”不是 volatile 的,这个操作会这样对待它吗?即它会从内存中获取这个变量的最新值吗?如果是这样,那是用写读“原子”吗?我知道 Interlocked.Exchange 的主要目的是您将获得 'a' 的先前值作为新写入的原子操作。但我的主要困惑在于“b”的值实际写入了“a”。
我的第二个问题与这篇文章中的一句话有关:
http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/
“一个有趣的点是,根据此处和此处记录的内存模型,C# 中的所有写入都是 volatile 的,并且大概也是这样实现的。C# 语言的 ECMA 规范实际上定义了一个较弱的模型,其中写入不是默认情况下是易变的。”
这是真的吗?如果是这样,如果不关心“a”的先前值,是否存在 Interlocked.Exchange 的目的? (关于我的第一个例子)。我没有在 StackOverflow 上看到关于每次写入都不稳定的任何其他文章或评论。但是,我知道写入是原子的。
编辑:如果我的第一个问题的答案是“b”不被视为易变的,而我的第二个问题的答案是写入确实是易变的,那么后续问题是,interlocked.exhange 何时有用,如果我们不关心 'a' 的先前值?
最佳答案
传递给 Exchange
的变量(或传递给任何方法的任何 volatile 变量)在传递时不保留“波动性”......实际上没有必要让它成为 volatile
(在方法调用期间)因为 volatile
唯一做的就是确保编译器不优化变量的使用(这通常意味着优化写入寄存器因此该值只能由单个处理器“看到”)。在 x86/x64 以外的处理器上,这有时意味着保证获取或释放语义的指令。 .NET 不使用寄存器来传递参数,因此 volatile 不会影响传递的参数的“波动性”。由于内存模型的可见性保证,它必须始终从内存中获取最新值
RE 问题 2:引用“有点”是真的,这取决于字段的声明,有可见性保证 w.r.t.字段;但如果没有“ volatile ”字段访问,则可以在某些使用阶段将其优化为寄存器,从而可能对其他处理器隐藏某些写入。
Interlocked
交换使不是原子的操作看起来是原子的。交换本质上类似于:
var x = someVariable;
someVariable = y;
无论 someVariable
的类型如何,这都不能是原子的。 Exchange
使此操作成为原子操作。对于 double
、long
(32 位)等非原子类型,这也是原子的。
Exchange
为实现原子性所做的部分工作是使用内存栅栏——这使得写入可见,并且不会与内存之后的指令序列中相同内存地址的读取重新排序围栏。
如果您不关心“a”的先前值,为什么要使用 Exchange
?如果您不关心实际的“交换”,那么 VolatileWrite
似乎更合适。
或者,如果不需要“exchange”,您可以编写线程安全代码来为“A=B”建模,如下所示:
Thread.MemoryBarrier();
A=B;
FWIW,Interlocked
是部分围绕某些处理器中的比较和交换 (CAS) 指令建模的。这些指令允许您在一条指令中执行这两个操作(使其成为原子)。如果没有像 Interlocked
这样的东西,编译器可能很难推断出应该使用这些 CAS 指令之一。此外,Interlocked
在不支持这些 CAS 指令(以及其他可能的非原子指令,如 inc 和 dec——可能并非在所有处理器上都可用)的处理器上提供原子用法
关于c# - Interlocked.Exchange 说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13013555/
我希望以原子方式递增静态变量,同时以无锁方式将新值分配给实例字段。目标是让每个对象在创建时获得一个唯一的、递增的 ID,这样两个对象就不可能获得相同的 ID。 下面的代码能实现吗? class MyC
我在优化程序时遇到了一些奇怪的性能结果,这些结果显示在以下 BenchmarkDotNet 基准测试中: string _s, _y = "yo"; [Benchmark] public void E
很抱歉问了这么长的问题,但是有 Jon Skeet 的引用资料,所以对某些人来说可能是值得的。 简而言之: Interlocked.Read/Interlocked.Exchange 在 Mono 框
在我阅读 ReaderWriterLockSlim 时锁机构,There was this guy谁建议 Interlock函数可用于更精细的锁定 另外,我发现 here马克的另一个回答: ...Wr
假设我有一个变量“counter”,并且有几个线程使用Interlocked访问和设置“counter”的值,即: int value = Interlocked.Increment(ref coun
Interlocked.CompareExchange() 方法 ( docs ) 粗略地说: “我有一个变量,我想我知道它当前有什么值。如果我是对的,请将值更改为那个”。 关键是这个方法可以用来在多
例子: Thread a: Interlocked.Increment(ref x); Thread b: int currentValue = x; 假设线程 b 在线程 a 之后执行,线程 b
我们有一个方法可以维护我们应用程序中所有事件的全局序列索引。由于它是网站,因此预计具有线程安全的这种方法。线程安全的实现如下: private static long lastUsedIndex =
我见过很多不错的对象池实现。例如:C# Object Pooling Pattern implementation . 但似乎线程安全的总是使用锁,从不尝试使用 Interlocked.* 操作。 编
是 Interlocked.Increment(ref x)比 x++ 快或慢对于各种平台上的整数和多头? 最佳答案 它较慢,因为它强制操作以原子方式发生,并且充当内存屏障,消除了处理器围绕指令重新排
我有一个应用程序,它不断地(+-100 毫秒)从 PLC 读取订单,然后将它们放入模型中,然后由多个客户端读取。为此,我使用了 lock 语句。 订单阅读线程: lock (model) { //up
我们有一个并发的多线程程序。我如何使样本数每次增加 +5 间隔? Interlocked.Increment 是否有间隔过载?我没有看到它列出。 Microsoft Interlocked.Incre
作为一个线程菜鸟,我正在尝试找到一种不锁定对象的方法,允许我将线程池任务排入队列,这样它的最大并行度 = 1。 这段代码会按照我的想法行事吗? private int status; private
这仅涉及 Microsoft/Visual Studio 和 Intel/AMD 特定实现。 比如说,如果声明一个全局变量: volatile __declspec(align(16)) ULONG
我有几个简单的(希望是)问题,我一直无法找到答案 - 假设我有多个线程可以访问的对象 a、b。 Interlocked.Exchange(ref a, b) 如果“b”不是 volatile 的,这个
我正在编写一个需要使用 Interlocked 的通用类。 T test1, test2; Interlocked.Exchange(ref test1, test2); 这不会编译。所以我是否被迫使
我有一些遗留代码使用 Interlocked.Equals 来比较值。这些值可以是两个 bool 值,也可以将一个结构数组与 null 进行比较。 Resharper 提示 Interlocked.E
如果我要使用某种算法,在 C++ 中对变量使用 InterlockCompareExchange 操作来确定特定线程是否正在写入一组数据(通过创建我自己的小锁),我如何确保如果数据存储在 i7 上的
假设我们有这样一个类: public class Foo { private Bar bar = new Bar(); public void DoStuffInThread1()
来自文档 here :“此类的方法有助于防止在线程正在更新可由其他线程访问的变量时调度程序切换上下文时可能发生的错误...” 此外,对 this question 的回答声明“互锁方法在任何数量的内核
我是一名优秀的程序员,十分优秀!