● 编译器,CLR或者CPU可能会更改指令的顺序来提高性能
● 编译器,CLR或者CPU可能会通过缓存来优化变量,这种情况下对其他线程是不可见的。
示例:多核CPU中的单例模式需要用内存墙来保证线程安全。
public sealed class Singleton {
private static Singleton instance;
static readonly object padlock = new object();
public static Singleton Instance {
get {
if ( instance == null ) {
lock ( padlock ) {
if ( instance == null ) {
Singleton newVal = new Singleton();
System.Threading.Thread.MemoryBarrier();
instance = newVal;
}
}
}
return instance;
}
}
}
示例:CPU缓存变量
using System;
using System.Threading;
namespace ConsoleApp14
{
class Program
{
static void Main(string[] args)
{
//在 Release 模式下,选择 [开始执行(不调试)],while将陷入死循环。
//这是因为complete值被缓存到了CPU寄存器中,所以complete一直为false。
bool complete = false;
var t = new Thread(() =>
{
bool toggle = false;
while (!complete)
{
//重点:加句内存屏障,方可及时读取complete的最新值
Thread.MemoryBarrier();//不加这句会陷入死循环
toggle = !toggle;
}
});
t.Start();
Thread.Sleep(1000);
//release模式下,改变了值,但t线程无法及时感知
complete = true;
t.Join(); // 等待t线程返回
Console.ReadLine();
}
}
}