- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
最近我发现this article这解释了如何在 C# 中实现线程安全单例模式
。但是我想知道让你的单例线程安全有多重要以及让你的单例类非线程安全的危险是什么。考虑一个非常简单的非线程安全的单例模式实现:
public class ThreadNotSafeSingleton
{
public static ThreadNotSafeSingleton Instance
{
get
{
if (_instance == null)
{
_instance = new ThreadNotSafeSingleton();
}
return _instance;
}
}
private static ThreadNotSafeSingleton _instance;
private ThreadNotSafeSingleton()
{
}
}
现在说一下,由于这段代码是非线程安全的,所以会有两个线程进入这行代码_instance = new ThreadNotSafeSingleton();
。在这种情况下,第一个线程将初始化 _instance
字段,然后第二个线程将再次初始化 _instance
字段,结果您将有一个 _instance
存在于您的应用程序中。
那么这里有什么大不了的呢?我知道,如果您有更复杂的代码,并且您的构造函数运行一些其他可能不是线程安全的代码,那可能很危险。但是如果你的单例那么简单,非线程安全会有什么问题吗?
最佳答案
由于单例模式将类限制为只有一个实例,因此您的方法违反了该模式。
如果出于任何原因这对您的实现来说是可行的,并且我们遵循您陈述的示例,则两个并发访问中的每一个都很有可能获得另一个 ThreadNotSafeSingleton
实例。如果编译器决定不需要回读它刚刚在返回之前写入的 _instance
变量,则可能由于优化而发生这种情况。此优化行为由 C# 实现的内存模型定义。
volatile
关键字经常被引用为可能的解决方案,但它不会解决同步问题(正如 BionicCode 所指出的),当线程 1 通过 if (_instance == null)
行并进入休眠状态,然后线程 2 也评估相同的 if 并开始实例化单例。当线程 1 稍后醒来时,它将实例化另一个单例。
关于c# - 非线程安全单例的危险是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56713901/
我是一名优秀的程序员,十分优秀!