此C#代码是否会因为寄存器或缓存中的值永远不会写回主内存而失败?在这篇文章中:http://msdn.microsoft.com/en-us/magazine/jj883956.aspx作者声明以下代码可能由于“循环读取提升”而失败:classTest{privatebool_flag=true;publicvoidRun(){//在另一个线程上将_flag设置为falsenewThread(()=>{_flag=false;}).Start();//轮询_flag字段直到它被设置为falsewhile(_flag);//循环可能永远不会终止!在循环读取提升中,由于单线程假设,编译器可能会将上面的while循环更改为以下内容:if(_flag){while(true);我想知道:如果编译器不执行该优化,由于一个处理器更新寄存器或缓存中的_flag并且永远不会将该缓存刷新回多处理器机器,因此循环仍然可能在多处理器机器上永远运行正在运行的内存被其他线程读取?我读过“C#写入是易变的”,但我链接到的文章说ECMA规范实际上并不能保证这一点,而且在ARM上也没有实现。我试图弄清楚我必须做什么才能编写适用于所有平台的线程代码。这是一个相关的问题:C#线程是否可以实际缓存一个值并忽略其他线程对该值的更改?但我认为接受的答案中的代码可能通过循环读取提升进行了优化,因此它无法证明内存可见性......如果编译器不执行该优化,由于处理器更新了寄存器或缓存中的_flag并且从不将该缓存刷新回另一个线程可读的内存,是否仍然可以在多处理器机器上永远运行循环?是的。我读过“C#写入是易变的”,但我链接到的文章说ECMA规范实际上并不能保证这一点,而且在ARM上也没有实现。那有什么关系?主线不是写,而是读。我试图弄清楚我必须做什么才能编写适用于所有平台的线程代码。如果他们真的想要你,那不是偏执狂。穿线很难。做我做的:将共享内存的低级操作留给专家。使用最高级别的抽象和专家为您编写的抽象来编写代码。你几乎不应该像你描述的那样编写代码,不是因为它是错误的——尽管它是——而是因为它处于错误的抽象级别。如果想表达“这个操作可以取消”的想法,那就用CancellationToken;这就是他们的目的。如果要表示“这项工作在未来产生结果”的概念,请使用Task;这就是他们的目的。不要试图自己做;让微软为你做。更新:有关C#中的线程安全、易变语义、低锁技术的更多信息,以及为什么您应该避免自己做所有这些,请参阅:Vance2005年关于低锁技术的优秀文章:http://msdn.microsoft。com/en-us/magazine/cc163715.aspx我2011年的系列三篇文章从这里开始:Atomicity,volatilityandimmutabilityisdifferent,partone特别是第三篇和你相关,但是前两篇也可以很有趣。JoeDuffy重申了为什么不应该使用volatile:http://joeduffyblog.com/2010/12/04/sayon??ara-volatile/我在2014年发表的两篇AskTheBugGuys文章:http://blog.coverity.com/2014/03/12/can-skip-lock-reading-integer/http://blog.coverity.com/2014/03/26/reordering-optimizations/我给了那些合理的阅读顺序;如果您觉得Vance的文章太难,请尝试从我的三部曲系列开始,然后再返回。以上是C#学习教程:这段C#代码会不会因为寄存器或缓存中的值永远不会写回主存而失败?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
