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

时间:2017-05-20 12:27:05

标签: c# .net volatile ref

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的任何其他原因吗?

2 个答案:

答案 0 :(得分:9)

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

您可以使用Debug>查看计算机上的内容。 Windows>拆卸。您必须切换到发布版本并使用工具>选项>调试>一般>解开“抑制JIT优化”。大多数程序员会对他们看到的内容感到满意:

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

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

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

比较那样的几个内在函数,例如Math.Sqrt()。大多数处理器都将它作为内置的机器代码指令。

答案 1 :(得分:0)

因为在.NET中,默认情况下参数是按值传递的。