我想编写一个程序,它可以直观地说明volatile关键字的行为.理想情况下,它应该是一个程序,它执行对非易失性静态字段的并发访问,并因此而获得不正确的行为.
在同一程序中添加volatile关键字应该可以解决问题.
那是我无法实现的.即使尝试多次,启用优化等,我总是会在没有'volatile'关键字的情况下获得正确的行为.
你对这个话题有什么看法吗?你知道如何在一个简单的演示应用程序中模拟这样的问题吗?它取决于硬件吗?
小智 101
我已经实现了一个有效的例子!
从wiki收到的主要想法,但对C#进行了一些更改.维基文章为C++的静态字段演示了这一点,它看起来像C#总是小心地将请求编译到静态字段......我用非静态字段做例子:
如果您在发布模式下运行此示例并且没有调试器(即使用Ctrl + F5),则该行将while (test.foo != 255)优化为"while(true)"并且此程序永远不会返回.但是在添加volatile关键字之后,您总能获得"确定".
class Test
{
/*volatile*/ int foo;
static void Main()
{
var test = new Test();
new Thread(delegate() { Thread.Sleep(500); test.foo = 255; }).Start();
while (test.foo != 255) ;
Console.WriteLine("OK");
}
}
Run Code Online (Sandbox Code Playgroud)
Cra*_*ntz 21
是的,它依赖于硬件(如果没有多个处理器,你不太可能看到问题),但它也依赖于实现.CLR规范中的内存模型规范允许Microsoft实现CLR不一定要做的事情.我在volatile关键字上看到的最好的文档是Joe Duffy的博客文章.请注意,他说MSDN文档"极具误导性".
当没有指定'volatile'关键字时,发生错误并不是真正的问题,更多的是当未指定错误时可能发生错误.一般来说,你会知道什么时候比编译器更好!
最简单的思考方式是编译器可以,如果需要,可以内联某些值.通过将值标记为volatile,您告诉自己和编译器该值可能实际发生更改(即使编译器不这么认为).这意味着编译器不应该内联值,保持缓存或提前读取值(尝试优化).
此行为与C++中的关键字实际上不是同一个关键字.
MSDN 在这里有一个简短的描述.这可能是关于波动率,原子性和联锁主题的更深入的帖子
| 归档时间: |
|
| 查看次数: |
14206 次 |
| 最近记录: |