c# - 使用 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;
}
}
解决方案
这称为双重检查锁定。
但是,双重检查锁定要求基础字段为volatile
1。
简而言之,分配是原子的,但需要在不同的内核/CPU 之间进行同步(全围栏,通过锁)。另一个核心同时读取该值的原因可能会缓存过时的值1。
有几种方法可以使代码线程安全:
- 避免双重检查锁定,并简单地执行
lock
语句中的所有内容。 - 使用关键字使字段可变。
volatile
- 使用
Lazy
保证是线程安全的类。
注意:完全无人看守的二传手进一步增加了复杂性3 ..
但是,在您的情况下,使用双重检查锁定可能会与单次检查和锁定volatile
字段一起正常工作,但我认为您最好的选择是填满lock
所有内容并确保安全
public static MyClass Instance
{
get
{
lock(_padlock)
{
if(_instance == null)
_instance = new MyClass();
return _instance;
}
}
set
{
lock(_padlock)
{
_instance = value;
}
}
}
注意:是的,它会导致性能损失
参考
来自@user2864740的3条评论
其他资源
推荐阅读
- python - 简单的python问题:两个相等的列表表现不同
- java - 为什么我一直打印每套,我该如何停止
- python - 如何在日志处理程序中控制请求对象
- python - How to find .pyc files with python version > 3.0 for OpenCV
- angular-cli - @angular/cli 没有要求路由或样式表
- xamarin.android - PDFTron 中的 CustomRelativeLayout Layout_with 和 layout_height 不起作用
- parse-platform - saveInBackground 或 saveEventually 返回回调中保存的对象吗?
- google-cloud-platform - Save Bigquery results to JSON in Google Composer
- python - Is there any possibility to separate keyword if there are more than one in one row
- javascript - Threeejs 加载的 FBX 不显示所有模型部分