Мне тут стало интересно, такой синглтон потокобезопасный? Двух экземплятор не создасться?
public class MySingleton
{
private static MySingleton _instance = new MySingleton();
public static MySingleton Instance
{
get
{
return _instance;
}
}
}
Данная информация предоставляется на условиях «КАК ЕСТЬ», без предоставления каких-либо гарантий и прав. Используя данную информацию, вы соглашаетесь с тем, что (i) Майкрософт не несет ответственности за использование вами данной информации и (ii) вы принимаете на себя весь риск, связанный с использованием данной информации.
Здравствуйте, adontz, Вы писали:
A>Мне тут стало интересно, такой синглтон потокобезопасный? Двух экземплятор не создасться?
Да, там специально при обращении к статическим полям вставляется код для проверки гарантированной инициализации.
В некоторых случаях это ведет к тормозам, кстати.
А вот кусочек из MSDN:
.NET Singleton Example
// .NET Singletonsealed class Singleton
{
private Singleton() {}
public static readonly Singleton Instance = new Singleton();
}
This version is dramatically simpler and more intuitive. Is it still a singleton? Let's look at what changed and then decide. We modified the class itself to be sealed (non-inheritable), the lazy initialization code is removed, the Instance() method is removed, and we modified the _instance variable extensively. The changes to the _instance variable include modifying the access level to public, marking the variable as read-only, and initializing the variable at declaration time. Here we can directly define the behavior we want and not be concerned with potential unwanted side effects of the implementation. So what about the advantages of using lazy initialization and the hazards of multiple threads? All of the correct behaviors are built into the .NET Framework. Let's take the first case, lazy initialization.
The main reasons for using lazy initialization initially were to get the behavior of having an instance created on only the first call to the Instance() method, and because there was some openness in the C++ spec that did not define the exact initialization order of static variables. To get desired singleton behavior in C++, a workaround that involved the use of lazy initialization was necessary. What we really care about is that we get the instance created either on or just before the first call to (in this case) the Instance property, and that we have a defined initialization order for static variables in a class. With the .NET Framework, this is exactly the behavior we get. The Framework, during the JIT process, will initialize the static property when (and only when) any method uses this static property. If the property is not used, then the instance is not created. More precisely, what happens during JIT is that the class gets constructed and loaded when any static member of the class is used by any caller. In this case the result is the same.
What about thread-safe initialization? The Framework addresses this too. The Framework internally guarantees thread safety on static type initialization. In other words, in the example above, there is only one instance that would ever be created of the Singleton class. Note also that the property field used to hold the instance of the class is called Instance. This choice better illustrates that this value is an instance of the class as part of the discussion in this article. In the Framework itself there are several classes that use this type of singleton, although the property name used is called Value instead. The concept is exactly the same.
В этом блоге увидел другой способ создания синглтона:
public class Singleton
{
private static Singleton _instance;
public static Singleton GetInstance()
{
if (_instance == null)
{
lock (typeof(Singleton))
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
Плюс такой реализации, в том, что объект создается при первом вызове метода GetInstance(), т.е. нет вызовов — нет объекта.
На мой взгляд, использовать данную реализацию стоит только в каких то оссобенных и редких случаях.
В этом блоге увидел другой способ создания синглтона:
public class Singleton
{
private static Singleton _instance;
public static Singleton GetInstance()
{
if (_instance == null)
{
lock (typeof(Singleton))
{
if (_instance == null)
{
_instance = new Singleton();
}
}
}
return _instance;
}
}
Плюс такой реализации, в том, что объект создается при первом вызове метода GetInstance(), т.е. нет вызовов — нет объекта.
На мой взгляд, использовать данную реализацию стоит только в каких то оссобенных и редких случаях.
>и для чего тут нужен lock если он не обрамляет if ?
Такая конструкция используется для того, чтобы устранить синхронизацию при каждом вызове этого метода. Синхронизация будет производиться до тех пор, пока _instance будет null.
Второе условие проверки на null, нужно для избежания создания нескольких экземпляров класса Singleton (так как несколько потоков могут пройти первое условие проверки на null). Пример Rafiki не учитывает эту ситуацию.
Я думаю, что единственное чего здесь не хватает, для полноценной потокобезопасности — это объявление поля _instance как volatile, для обеспечения атомарности сравнения (_instance == null).
Здравствуйте, Александр Сергеевич, Вы писали:
АС>Здравствуйте, valmond, Вы писали: V>>См. внимательнее. V>>Стандартная двойная проверка АС>А зачем два if? А почему не один в lock?
После первого if-a мы проверяем, что достаточное условие для наложения лока и создания объекта выполняется.
Накладываем lock и проверяем, что после проверки достаточного условия второй поток еще не создал этот инстанс. Т.е. проверяем необходимое условие и делаем выводы.
Здравствуйте, olegmad, Вы писали:
O>Плюс такой реализации, в том, что объект создается при первом вызове метода GetInstance(), т.е. нет вызовов — нет объекта. O>На мой взгляд, использовать данную реализацию стоит только в каких то оссобенных и редких случаях.
Есть более элегантное решение:
public sealed class Singleton {
private sealed class SingletonInstanceHolder {
private SingletonInstanceHolder() {}
public static readonly Singleton SingletonInstance = new Singleton();
}
private Singleton() {}
public static Singleton Instance {
get { return SingletonInstanceHolder.SingletonInstance; }
}
}
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Lloyd, Вы писали:
L>>И вместо Reflection-а будет просто new T();
А>+ "дырка" в паттерне
Да, вот, собственно говоря, поэтому и остановился на рефлекшине
Если скорость большая не нужна...
Кроме того у меня там еще есть "точка расширения" — можно подсунуть другой тип с клиентской реализацией —
которую я убрал из примера.
Re[5]: потокобезопасный Singleton
От:
Аноним
Дата:
09.08.05 10:43
Оценка:
Здравствуйте, hugo, Вы писали:
H>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Lloyd, Вы писали:
L>>>И вместо Reflection-а будет просто new T();
А>>+ "дырка" в паттерне H>Да, вот, собственно говоря, поэтому и остановился на рефлекшине H>Если скорость большая не нужна...
Думается, разница в скорость здесь не критична
H>Кроме того у меня там еще есть "точка расширения" — можно подсунуть другой тип с клиентской реализацией — H>которую я убрал из примера.
А вот паттерны скрещивать не стоит (фабрика и синглетон).
Здравствуйте, Аноним, Вы писали:
H>>Кроме того у меня там еще есть "точка расширения" — можно подсунуть другой тип с клиентской реализацией — H>>которую я убрал из примера.
А>А вот паттерны скрещивать не стоит (фабрика и синглетон).
А если надо? Тут либо фабрика с сингелтоном, либо наоборот
Что еще можете посоветовать?