我想大多数人都知道在Release模式下构建时会发生以下问题(代码取自C#中的Threading):
static void Main()
{
bool complete = false;
var t = new Thread (() =>
{
bool toggle = false;
while (!complete) toggle = !toggle;
});
t.Start();
Thread.Sleep (1000);
complete = true;
t.Join(); // Blocks indefinitely
}
Run Code Online (Sandbox Code Playgroud)
由于编译器优化缓存了值,complete从而阻止子线程看到更新的值.
但是,改变上面的代码:
class Wrapper
{
public bool Complete { get; set; }
}
class Test
{
Wrapper wrapper = new Wrapper();
static void Main()
{
var test = new Test();
var t = new Thread(() =>
{
bool toggle = false;
while (!test.wrapper.Complete) toggle = !toggle;
});
t.Start();
Thread.Sleep(1000);
test.wrapper.Complete = true;
t.Join(); // Blocks indefinitely
}
}
Run Code Online (Sandbox Code Playgroud)
使问题消失(即子线程能够在1秒后退出)而不使用volatile内存栅栏或任何其他引入隐式栅栏的机制.
添加完成标志的封装如何影响其在线程之间的可见性?
我想你的答案在你的问题中:
由于编译器优化缓存完整的值,从而阻止子线程看到更新的值.
只要有意义/被认为安全合理地实施,就会执行编译器/ JIT优化.因此,您发现未按预期方式执行优化的情况 - 可能有充分的理由(某人检测到此使用模式和阻止优化)或者恰好没有进行优化(最有可能).
| 归档时间: |
|
| 查看次数: |
247 次 |
| 最近记录: |