试图了解何时锁定静态变量被认为是最佳实践。静态实例 setter 是线程安全的吗?如果不是,应该是,为什么(不使其成为线程安全的后果是什么)?
class MyClass
{
private static MyClass _instance;
private static readonly object _padlock = new object();
public static MyClass Instance
{
get
{
if(_instance == null)
{
lock(_padlock)
{
if(_instance == null)
{
_instance = new MyClass();
}
}
}
return _instance;
}
set => _instance = value;
}
}
请您参考如下方法:
这称为双重检查锁定。
但是,双重检查锁定要求底层字段是volatile1。
简而言之,分配是原子的,但它需要在不同的核心/CPU 之间同步(完全隔离,通过锁)。原因是另一个核心同时读取该值可能会缓存一个过时的值1。
有几种方法可以使代码线程安全:
- 避免双重检查锁定,并简单地执行
lock语句中的所有操作。 - 使用
volatile关键字使字段volatile。 - 使用
Lazy类,保证线程安全。
注意:完全无人看守的二传手进一步增加了复杂性3..
但是,在您的情况下,使用双重检查锁定 可能会在使用 volatile 字段进行一次检查和锁定时正常工作,但我认为您最好的选择是完全锁定一切并保证安全
public static MyClass Instance
{
get
{
lock(_padlock)
{
if(_instance == null)
_instance = new MyClass();
return _instance;
}
}
set
{
lock(_padlock)
{
_instance = value;
}
}
}
注意:是的,它会导致性能下降
引用
3 来自 @user2864740 的评论
其他资源
