我已经被认为如果多个线程可以访问变量,那么所有对该变量的读取和写入都必须受到同步代码的保护,例如"lock"语句,因为处理器可能会在中途切换到另一个线程写.
但是,我正在使用Reflector查看System.Web.Security.Membership并找到如下代码:
public static class Membership
{
private static bool s_Initialized = false;
private static object s_lock = new object();
private static MembershipProvider s_Provider;
public static MembershipProvider Provider
{
get
{
Initialize();
return s_Provider;
}
}
private static void Initialize()
{
if (s_Initialized)
return;
lock(s_lock)
{
if (s_Initialized)
return;
// Perform initialization...
s_Initialized = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
为什么s_Initialized字段在锁外读取?另一个线程难道不能同时写入它吗?变量的读写是否是原子的?
这是一个复杂的问题,请在回答之前仔细考虑.
考虑这种情况.两个线程(读取器和写入器)访问单个全局int.这样安全吗?通常,我会毫不犹豫地回答,是的!
然而,在我看来,Herb Sutter并不这么认为.在他关于有效并发的文章中,他讨论了一个有缺陷的无锁队列和纠正的版本.
在第一篇文章的末尾和第二篇文章的开头,他讨论了很少考虑的变量特征,即写入顺序.Int是原子的,很好,但是int不一定是有序的,它可以破坏任何无锁算法,包括我上面的场景.我完全同意,保证现有和未来所有平台上正确的多线程行为的唯一方法是使用原子(AKA内存屏障)或互斥.
我的问题; 在实际硬件上写的重写是否有问题?还是多线程的偏执狂只是迂腐?
那么经典的单处理器系统呢?
那些更简单的RISC处理器如嵌入式电源?
澄清:我对Sutter先生所说的硬件(处理器/缓存)重新排序变量写入更感兴趣.我可以阻止优化器使用编译器开关破坏代码或手动检查汇编后编译.但是,我想知道硬件是否仍然可以在实践中搞乱代码.