如果编译器不执行该优化,由于一个处理器更新寄存器或缓存中的 _flag 并且从不将该缓存刷新回另一个线程可读的内存,循环是否仍然有可能在多处理器计算机上永远运行?
Yes.
我读过“C# 写入是易失性的”,但我链接的文章说这实际上并没有得到 ECMA 规范的保证,而且在 ARM 上也不是这样实现的。
这有什么关系?主线程不是写,而是读。
我试图弄清楚我必须有多偏执才能编写适用于所有平台的线程代码。
如果他们真的想抓你,那就不是偏执狂。穿线很难。做我所做的:将共享内存的低级操作留给专家。
使用以下代码编写代码最高可能的抽象级别,其中包含专家为您编写的摘要。您几乎不应该按照您所描述的方式编写代码,不是因为它是错误的(尽管它是错误的),而是因为它处于错误的抽象级别。如果你想表达“这个操作可以被取消”的想法,那么使用CancellationToken
;这就是他们的目的。如果你想表达“这项工作在未来产生结果”的概念,请使用Task<T>
;这就是他们的目的。不要尝试自己推出;让微软为您做这件事。
更新:有关 C# 中的线程安全、易失性语义、低锁技术和为什么你应该避免自己做所有这些事情, see:
Vance 在 2005 年发表了一篇关于低锁技术的精彩文章:
http://msdn.microsoft.com/en-us/magazine/cc163715.aspx http://msdn.microsoft.com/en-us/magazine/cc163715.aspx
我的 2011 年系列三篇文章从这里开始:
http://ericlippert.com/2011/05/26/atomicity-volatility-and-immutability-are- Different-part-one/ http://ericlippert.com/2011/05/26/atomicity-volatility-and-immutability-are-different-part-one/
特别是第三个与您相关,但前两个可能也很有趣。
Joe Duffy 重申了为什么不应该使用 volatile:
http://joeduffyblog.com/2010/12/04/sayonara-volatile/ http://joeduffyblog.com/2010/12/04/sayonara-volatile/
我 2014 年的两篇 Ask The Bug Guys 文章:
http://blog.coverity.com/2014/03/12/can-skip-lock-reading-integer/ http://blog.coverity.com/2014/03/12/can-skip-lock-reading-integer/
http://blog.coverity.com/2014/03/26/reordering-optimizations/ http://blog.coverity.com/2014/03/26/reordering-optimizations/
我已经按照合理的阅读顺序给出了这些内容;如果您发现万斯的文章太难读,请尝试从我的三部分系列文章开始,然后再返回。