代码检查:可能错误实现了 Double-Check Locking 模式。 读取已检查字段的访问权限。
请考虑以下代码片段:
public class Foo
{
private static volatile Foo _instance;
private static readonly object Padlock = new object();
public static Foo GetValue()
{
if (_instance != null) return _instance;
lock (Padlock)
{
if (_instance != null) return _instance;
_instance = new Foo();
_instance.Init();
}
return _instance;
}
private void Init()
{
// object initialization
}
}
如果我们假设 Init() 是用于初始化 Foo 状态的方法,那么上述代码在多线程环境中可能无法按预期运行。
可能会出现一种情况,一个线程执行了 _instance = new Foo(); 但尚未执行 _instance.Init();。 如果此时其他线程调用 GetValue() ,该方法会发现 _instance 不为 null,并将一个未初始化的实例返回给调用者。
对于上述代码,有两种方法可以解决此问题。
第一种,也是最明显的方法,是将 Init() 的内容移到一个私有构造函数中。
第二种方法是在一个未检查的变量中执行初始化,然后将其赋值给已检查的变量,从而消除问题。 通过这种方式, _instance 只有在已经初始化后才会变为非 null。 上述示例中 锁定 语句中的代码可以重写为:
if (_instance != null) return _instance;
var temp = new Foo();
temp.Init();
_instance = temp;
StackOverflow 上的这个回答解释了此模式的其他可能问题,以及为什么 _instance 应该声明为 volatile。
最后修改日期: 2025年 9月 26日