Идиома Double-Check Locking [Lea99], предоставленная Microsoft здесь , удивительно похожа на предоставленный вами код, к сожалению, это не соответствует стандарту CLI ECMA для пуританского взгляда на потокобезопасный код и может не работать правильно во всех ситуациях.
В многопоточной программе разные потоки могут пытаться создать экземпляр класса одновременно. По этой причине реализация Singleton, которая полагается на оператор if, чтобы проверить, является ли экземпляр пустым , не будет поточно-безопасным . Не пишите такой код!
Простой, но эффективный способ создания поточно-ориентированного синглтона - это использовать вложенный класс для его создания. Ниже приведен пример ленивого экземпляра синглтона:
public sealed class Singleton
{
private Singleton() { }
public static Singleton Instance
{
get
{
return SingletonCreator.instance;
}
}
private class SingletonCreator
{
static SingletonCreator() { }
internal static readonly Singleton instance = new Singleton();
}
}
Использование:
Singleton s1 = Singleton.Instance;
Singleton s2 = Singleton.Instance;
if (s1.Equals(s2))
{
Console.WriteLine("Thread-Safe Singleton objects are the same");
}
Универсальное решение:
public class Singleton<T>
where T : class, new()
{
private Singleton() { }
public static T Instance
{
get
{
return SingletonCreator.instance;
}
}
private class SingletonCreator
{
static SingletonCreator() { }
internal static readonly T instance = new T();
}
}
Использование:
class TestClass { }
Singleton s1 = Singleton<TestClass>.Instance;
Singleton s2 = Singleton<TestClass>.Instance;
if (s1.Equals(s2))
{
Console.WriteLine("Thread-Safe Generic Singleton objects are the same");
}
Наконец, вот несколько выпущенное и полезное предложение - чтобы избежать взаимных блокировок, которые могут быть вызваны использованием ключевого слова lock, рассмотрите возможность добавления следующего атрибута для защиты кода только в открытых статических методах:
using System.Runtime.CompilerServices;
[MethodImpl (MethodImplOptions.Synchronized)]
public static void MySynchronizedMethod()
{
}
Ссылка:
- Кулинарная книга C # (О'Рейли), Джей Хилярд и Стивен Тейлет
- Шаблон дизайна C # 3.0 (О'Рейли), Джудит Бишоп
- CSharp-Online.Net - Шаблон проектирования Singleton: Потокобезопасный Singleton