using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new Object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
我不明白为什么要仔细检查! 我读到这个双重检查是为了解决线程并发问题 - 但是......
锁将解决它 - 所以我们需要首先'if'
如果这个单例没有第一个'if'它仍然是线程安全的 - 对吧?
如果第一个'if'为false - 那么thread1将初始化'instance'object =>现在,'instance'不为null并且thread1仍然在锁定块中===>>现在,thread2检查第一个'if'并将得到false =>所以他不会进入'lock'并且迫切地将返回实例并且thread2能够改变'instance'=>的属性。所以thread1&& thread2在同一'instance'object =>上'工作'那么线程安全在哪里......或者我在这里缺少的东西。
答案 0 :(得分:6)
1.锁将解决它 - 所以我们需要首先'如果'
所以除非你需要创建Singleton的新实例,否则你不会锁定thred
lock
是非常昂贵的操作,因此值得进行额外检查。
2.如果这个单例将没有第一个'if',它仍然是线程安全的 - 对吗?
是的,但速度要慢得多。
3.Thread1&& thread2在同一'instance'object =>上'工作'那么线程安全在哪里
这是单例的全部要点,所有线程只有一个实例。那是线程安全的事情......
答案 1 :(得分:2)
我假设如果ThreadA在lock
之前被中断; ThreadB成功完成单例的创建,然后当ThreadA恢复时,它将尝试在释放锁后重新创建单例。
答案 2 :(得分:0)
if检查单例是否已经实例化,如果它没有创建新的实例。锁定确保线程安全。
没有if它会在每次调用时创建一个新的instace(不是单例的想法)。如果没有锁定,两个线程就可以模拟地创建一个实例,因此可能存在两个实例。
如果您只使用单线程,则可以擦除锁定。否则(在mt上)强烈建议使用它。
答案 3 :(得分:0)
以下是马里兰大学关于推荐原因的一篇好文章(以及为什么它并不总是适用于现代优化编译器)如果你有时间,这是一本很好的读物。
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html