![]() |
1
7
问题不在于该方法是内联的——不管它是否是内联的,它都可能是通过内存访问执行有趣的事情时的抖动。 但是,我不相信 是 首先是一个问题。几年前,人们把它作为一个问题提出,但我相信这被认为是对记忆模型的错误解读。变量只有一个逻辑“读取”,而抖动不能优化这一点,使值在副本的一次读取和副本的第二次读取之间发生变化。 编辑:为了澄清,我完全理解为什么这会给你带来问题。基本上有两个线程修改同一个变量(因为它们使用捕获的变量)。代码完全有可能这样发生:
在这段代码中,这比正常情况下要稍微不明显,因为变量是一个捕获变量,而不是一个正常的静态/实例字段。但同样的原则也适用。 安全提升方法的要点是将引用存储在一个局部变量中,该变量 不能 从任何其他线程修改:
现在线程2是否更改
如果JIT
做
内联的
现在,关于你为什么 只有 在调试模式下看到了这种情况:我怀疑在附加了调试程序的情况下,线程之间的中断空间要大得多。可能还发生了一些其他的优化——但没有。 介绍 有破损的,没关系。 |
![]() |
2
5
这是内存模型问题。 基本上,问题是:如果我的代码只包含一个逻辑读取,优化器是否可以引入另一个读取? 令人惊讶的是,答案是: 也许吧 在clr规范中,没有什么可以阻止优化器这样做。优化不会破坏单线程语义,并且只保证为易失性字段保留内存访问模式(即使这是一个不是100%正确的简单应用程序)。 因此,无论使用局部变量还是参数,代码都是 非线程安全 . 但是,Microsoft.NET Framework记录了不同的内存模型。在该模型中,优化器不允许引入读取,并且 你的密码是安全的 (独立于内联优化)。 也就是说,使用[MethodImplOptions]似乎是一种奇怪的黑客行为,因为阻止优化器引入读取只是不内联的副作用。我会用易挥发的字段或线程来代替。 |
![]() |
3
1
使用正确的代码,优化不应该改变其语义。因此,如果代码中没有错误,优化器就不能引入任何错误。 |