В чем опасность использования Singleton в многопоточном приложении? - PullRequest
9 голосов
/ 07 апреля 2009

Я смотрю на использование синглтона в многопоточном сервисе Win для ведения журналов и хотел знать, с какими проблемами я могу столкнуться. Я уже настроил экземпляр get для обработки синхронизации с

    private static volatile Logging _instance;
    private static object _syncRoot = new object();

    private Logging(){}
    public static Logging Instance
    {
        get
        {
            if (_instance==null)
            {
                lock(_syncRoot)
                {
                    if (_instance == null)
                    {
                        _instance = new Logging();
                    }
                }
            }
            return _instance;
        }
    }

Есть ли еще что-то, о чем мне нужно беспокоиться?

Ответы [ 8 ]

13 голосов
/ 07 апреля 2009

Это выглядит довольно хорошо для меня.

Подробнее см. Реализация шаблона Singleton в C # .

Редактировать: Хотя, вероятно, следует поместить возврат в замок.

12 голосов
/ 07 апреля 2009

Это более информативно, чем все остальное.

То, что вы опубликовали, - это алгоритм двойной проверки блокировки - и то, что вы отправили , будет работать, насколько мне известно. (Что касается Java 1.5, он тоже работает там.) Однако он очень хрупкий - если вы ошибетесь, вы можете ввести очень тонкие условия гонки.

Я обычно предпочитаю инициализировать синглтон в статическом инициализаторе:

public class Singleton
{
    private static readonly Singleton instance = new Singleton();

    public static Singleton Instance
    {
        get { return instance; }
    }

    private Singleton()
    {
        // Do stuff
    }
}

(Добавьте статический конструктор, если вам нужна дополнительная лень.)

Эту модель легче понять, и в большинстве случаев она так же хороша.

На моей странице реализации синглтона C # (также ссылки Майкла) есть более подробная информация.

Что касается опасностей - я бы сказал, самая большая проблема в том, что вы теряете тестируемость. Вероятно, не слишком плохо для регистрации.

3 голосов
/ 07 апреля 2009

Синглтоны могут стать узким местом для доступа к ресурсу, воплощенному классом, и принудительно устанавливать последовательный доступ к ресурсу, который в противном случае мог бы использоваться параллельно.

В этом случае это может быть не плохо, потому что вы не хотите, чтобы в ваш файл одновременно записывались несколько элементов, и даже не думаю, что ваша реализация даст такой результат. Но об этом нужно знать.

2 голосов
/ 07 апреля 2009

Необходимо убедиться, что каждый метод в регистраторе безопасен для одновременного запуска, т. Е. Что они не записывают в общее состояние без надлежащей блокировки.

1 голос
/ 29 апреля 2009

Существует некоторая дискуссия относительно необходимости сделать первую проверку на нулевое значение, используя Thread.VolatileRead (), если вы используете шаблон блокировки с двойной проверкой и хотите, чтобы он работал на всех моделях памяти. Пример дебатов можно прочитать на http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/b1932d46-877f-41f1-bb9d-b4992f29cedc/.

Тем не менее, я обычно использую решение Джона Скита сверху.

1 голос
/ 07 апреля 2009

Лучшим предложением было бы установить регистратор на однопоточном этапе настройки, поэтому он гарантированно будет там, когда вам это нужно. В Windows Service OnStart - отличное место для этого.

Другой вариант - использовать метод System.Threading.Interlocked.CompareExchange (T%, T, T): T для переключения. Это менее запутанно и гарантированно работает.

System.Threading.Interlocked.CompareExchange<Logging>(_instance, null, new Logging());
1 голос
/ 07 апреля 2009

Вы используете двойную проверку блокировки , что считается анти-паттерном. Википедия содержит шаблоны с и без отложенной инициализации для разных языков.

После создания экземпляра синглтона вы, конечно, должны убедиться, что все методы поточно-ориентированы.

0 голосов
/ 07 апреля 2009

Я думаю, что если методы экземпляра Logging являются поточно-ориентированными, не о чем беспокоиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...