我想大多数人都知道在发布模式下构建时会发生以下问题(代码取自C# 中的线程):
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
}
由于编译器优化缓存的值,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
}
}
使问题消失(即子线程能够在 1 秒后退出),而无需使用volatile
、内存栅栏或任何其他引入隐式栅栏的机制。
完成标志的附加封装如何影响其在线程之间的可见性?