为什么Volatile.Read采用ref参数?

Dou*_*las 5 .net c# volatile ref

执行Volatile.Read只是在读取后插入一个内存屏障:

public static int Read(ref int location)
{
    var value = location;
    Thread.MemoryBarrier();
    return value;
}
Run Code Online (Sandbox Code Playgroud)

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

return Volatile.Read(ref _a) + Volatile.Read(ref _b);
Run Code Online (Sandbox Code Playgroud)

......相当于:

var a = _a;
Thread.MemoryBarrier();
var b = _b;
Thread.MemoryBarrier();
return a + b;
Run Code Online (Sandbox Code Playgroud)

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

public static int Read(int value)
{
    Thread.MemoryBarrier();
    return value;
}
Run Code Online (Sandbox Code Playgroud)

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

Han*_*ant 9

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

您可以使用Debug> Windows> Disassembly查看计算机上的内容.您必须切换到发布版本并使用工具>选项>调试>常规>取消选中"抑制JIT优化".大多数程序员会对他们看到的内容感到满意:

04CF0450  mov         ecx,dword ptr ds:[7C43ACh] 
Run Code Online (Sandbox Code Playgroud)

或换句话说:什么都没有.只是简单的记忆阅读没有障碍.Intel/AMD内核具有强大的内存模型,不需要屏障.但是,比方说,ARM核心确实需要变量的地址.Itanium也很弱,但它的抖动已经停止.

请注意,虽然你可能会感到高兴,但这也是一个相当糟糕的消息.你基本上不能依赖你的开发机器上的程序测试,并得出结论它是足够好的.或者换句话说,没有办法告诉你应该使用Volatile但是你忘记了.只有在设备上运行你的程序才会给你一个提示你弄错了.跳过确实需要很大的勇气lock:)

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

  • 您始终需要变量的地址来执行易失性读取,即上面代码片段中的 0x7C43AC。请注意,它如何简单地阻止您传递无法工作的属性,并且您将收到一个友好的编译时错误。而抖动不必在运行时弄清楚它是左值,如果不是则生成异常。 (2认同)