防止多线程中的错误优化

isp*_*iro 5 .net c# multithreading

以下代码:

while (x == 1) { ... }
Run Code Online (Sandbox Code Playgroud)

可能会被优化为

while (true) { ... }
Run Code Online (Sandbox Code Playgroud)

if x仅在另一个线程中分配.请参阅说明C#中volatile关键字的用法.那里的答案通过设置x来解决这个问题volatile.

然而,根据这三个贡献者(结合声誉超过100万:)看起来这不是正确的方法:))

Hans Passant 一个可重复使用的易失性用法示例 :"从不认为它在多线程场景中很有用."

Marc Gravell volatile函数的值在多线程中不会改变:"volatile不是我通常用来保证行为的语义"

Eric Lippert Atomicity,波动性和不变性是不同的,第三部分 :"我不鼓励你做一个不稳定的领域."

假设a Backgroundworker被视为与任何其他多线程一样(而不是具有一些内置机制来阻止优化) - 如何防止错误优化?

Eri*_*ert 13

你略微错误地描述了我的立场.使字段不稳定阻止优化.C#中没有破坏易失性.(C++,那是另一个故事.)

我的观点并不是挥发性不能按预期工作.我的观点是,首先在两个不同的线程上读取和写入相同的变量是一个坏主意.如果必须使用volatile来使程序正确,请考虑重新设计程序,使其根本不需要volatile.

  • @ispiro:我的观点是,有很多方法可以在逻辑上分享两个进程之间的数据,这些进程不涉及其中一个说"这是一个地址;观察它直到它发生变化".从其中一个中汲取灵感.或者,更好的是,**没有后台工作人员需要一直消耗新信息**.如果新信息出现,正如Brian建议的那样,*取消现有的后台工作人员*并*用新信息*开始一个新信息.有很多方法可以解决这个问题. (4认同)
  • 好的,同样的区别.共享内存是个坏主意.如果可以避免,请这样做. (2认同)
  • @ispiro:基本上我想在这里传达的直觉是:如果你的工作者在逻辑上是*服务器*,类似于web服务器,那么*为它创建一个客户端 - 服务器接口*.Web服务器不与其客户共享内存; 他们在客户端和服务器之间有一个定义良好的接口.相反,如果你的工作人员只是一个无人机完成某项任务并在完成任务时发出信号,那么就不要直接使用后台工作人员.创建一个`Task`并让Task Parallel Library处理进度,结果报告和取消. (2认同)