gpt4 book ai didi

c# - 允许 C# 编译器优化局部变量并从内存中重新获取值

转载 作者:可可西里 更新时间:2023-11-01 08:45:42 25 4
gpt4 key购买 nike

编辑:我问的是当两个线程在没有适当同步的情况下同时访问相同数据时会发生什么(在这次编辑之前,这一点没有明确表达)。

我对 C# 编译器和 JIT 编译器执行的优化有疑问。

考虑以下简化示例:

class Example {
private Action _action;

private void InvokeAction() {
var local = this._action;
if (local != null) {
local();
}
}
}

请忽略示例中读取 _action 可能会产生缓存和过时的值,因为没有 volatile 说明符或任何其他同步。这不是重点:)

是否允许编译器(或者实际上是运行时的抖动)优化对局部变量的赋值,而不是从内存中读取 _action 两次:

class Example {
private Action _action;

private void InvokeAction() {
if (this._action != null) {
this._action(); // might be set to null by an other thread.
}
}
}

当字段 _action 被并发分配设置为 null 时,可能会抛出 NullReferenceException

当然,在这个例子中这样的“优化”没有任何意义,因为将值存储在寄存器中并因此使用局部变量会更快。但在更复杂的情况下,是否可以保证在不从内存中重新读取值的情况下按预期工作?

最佳答案

我会(部分地)说与 mgronber 相反的 :-) Aaaah...最后我说的是同样的话...只是我引用了一篇文章 :-( 我会给他一个+1。

这是 ECMA 规范下的合法优化,但在 .NET >= 2.0“规范”下是非法优化。

来自Understand the Impact of Low-Lock Techniques in Multithreaded Apps

阅读这里 Strong Model 2: .NET Framework 2.0

第 2 点:

Reads and writes cannot be introduced.

下面的解释:

The model does not allow reads to be introduced, however, because this would imply refetching a value from memory, and in low-lock code memory could be changing.

但注意在同一页下,在 Technique 1: Avoiding Locks on Some Reads

In systems using the ECMA model, there is an additional subtlety. Even if only one memory location is fetched into a local variable and that local is used multiple times, each use might have a different value! This is because the ECMA model lets the compiler eliminate the local variable and re-fetch the location on each use. If updates are happening concurrently, each fetch could have a different value. This behavior can be suppressed with volatile declarations, but the issue is easy to miss.

如果您在 Mono 下编写,您应该被告知至少在 2008 年之前它一直在 ECMA 内存模型上工作(或者他们在他们的 mailing list 中写道)

关于c# - 允许 C# 编译器优化局部变量并从内存中重新获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7664046/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com