这个c#类的变量需要是volatile的吗?
这个c#类的变量需要是volatile的吗?
在下面的C#代码中,RunHelper()
只从Run()
中调用。由于编译器知道这一点,它是否会优化它,以便将if(terminate)
替换为if(false)
?
class Dummy { private bool terminate; public Dummy() { terminate = false; } public void KillDummy() // 从另一个线程调用 { terminate = true; } public void Run() { terminate = false; RunHelper(); } private void RunHelper() // 只从Run函数中调用 { if(terminate) { Console.WriteLine("Exiting"); } } }
这篇文章讨论了一个关于C#类变量是否需要使用volatile关键字的问题,并提供了解决方法。
文章首先提到,在从C#编译到IL时,对RunHelper的检查优化不会发生。然而,JIT(从IL编译到机器代码的过程)可能会将RunHelper内联到Run中,从而避免调用,造成你担心的优化问题。即使使用反射也无法解决这个问题,因为反射只能看到IL代码,而无法查看机器代码。
然后,文章讨论了线程可见性的问题。如果系统经常使用这段代码,它会将terminate变量保存在缓存中,而其他线程可能不会意识到对它所做的更改。因此,需要使用volatile关键字或类似的解决方案来解决这个问题。
文章还提到了volatile关键字的其他注意事项,但这些注意事项似乎不会影响你的代码。例如,重排序不仅发生在编译器中,CPU也可以进行重排序。使用volatile关键字可以对重排序进行约束。然而,写操作仍然可以在读操作之后被移动,需要使用完整的内存屏障来解决这个问题。如果遇到ABA问题,需要使用Interlocked类来解决,这意味着无法使用volatile关键字,而必须只使用Interlocked或volatile操作来处理变量。此外,还提到了一些相关链接供进一步参考。
总之,文章解释了为什么在某些情况下需要使用volatile关键字来确保线程可见性,并提供了其他解决方案来解决与volatile相关的其他问题。