Volatile.Read为什么要带ref参数?

Why does Volatile.Read take ref parameter?

Volatile.Read 的实现只是在读取之后插入一个内存屏障:

public static int Read(ref int location)
{
    var value = location;
    Thread.MemoryBarrier();
    return value;
}

因此,方法的用法是这样的...

return Volatile.Read(ref _a) + Volatile.Read(ref _b);

...等同于:

var a = _a;
Thread.MemoryBarrier();
var b = _b;
Thread.MemoryBarrier();
return a + b;

鉴于上述情况,如果参数不是 ref,结果行为不会相同吗?

public static int Read(int value)
{
    Thread.MemoryBarrier();
    return value;
}

我猜ref参数只是用来防止程序员传递变量以外的东西,比如Volatile.Read(2 + 3)。传入变量时,任何人都可以看到 ref 的任何其他原因吗?

这不是 真实 代码抖动完成后的样子。 Volatile.Read() 是一个 内在函数 。一个昂贵的词,意味着抖动根本不会编译该方法,而是用特定于处理器的机器代码版本替换它。您找到的代码只是一个占位符,可以用作机器上的后备,而不会出现像样的抖动。理论上。

您可以通过调试 > Windows > 反汇编查看您在计算机上获得的内容。您必须切换到发布版本并使用工具 > 选项 > 调试 > 常规 > 取消勾选 "Suppress JIT optimization"。大多数程序员会对他们看到的内容感到满意:

04CF0450  mov         ecx,dword ptr ds:[7C43ACh] 

或者换句话说:没有。只是一个没有障碍的普通内存读取。 Intel/AMD 核心具有不需要屏障的强大内存模型。但是,比方说,ARM 内核确实需要并且将需要变量的地址。安腾也弱了,不过抖音停产了

请注意,虽然您可能很高兴,但这也是个坏消息。您基本上不能依赖于在您的开发机器上测试您的程序并得出结论它已经足够好了。或者换句话说,无法判断您应该使用 Volatile 但您忘记了。只有 运行 您在设备上的程序会提示您弄错了。跳过lock确实需要很大的勇气:)

还有几个类似的内在函数,例如 Math.Sqrt()。大多数处理器都将其作为内置机器代码指令。

因为在 .NET 中参数默认按值传递。