Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Singleton и многопоточное программирование


Автор: shtuceron 13.4.2012, 09:18
Добрый день.

Скажите как ведет себя реализация паттерна одиночка в многопоточном программировании.

Я пишу многопоточное приложение, в котором используется один класс и мне очень не хотелось бы создавать экземпляры этого класса в каждом потоке, поэтому решил воспользоваться паттерном одиночка. Скажите могут ли возникнуть проблемы при использовании одного объекта в нескольких потоках (блокировку через lock я ставлю).

И еще вопрос, в классе (одиночка) у меня реализованы события, нужно ли для каждого потока создавать события, которые потоки будут обрабатывать? или достаточно в главном потоке определить события?

Спасибо.

Автор: azesmcar 13.4.2012, 09:25
Цитата(shtuceron @  13.4.2012,  09:18 Найти цитируемый пост)
Скажите как ведет себя реализация паттерна одиночка в многопоточном программировании.

Встречный вопрос. Какая реализация?
Ленивая инициализация НЕ потокобезопасна, но защищать инициализацию через lock идея не из лучших, лишний lock при каждом обращении. Лучше инициализировать в основном потоке, а потом спокойно использовать.

Цитата(shtuceron @  13.4.2012,  09:18 Найти цитируемый пост)
Скажите могут ли возникнуть проблемы при использовании одного объекта в нескольких потоках 

Смотря какое использование. Чтение потокобезопасно, запись из нескольких потоков необходимо защищать через lock.

Цитата(shtuceron @  13.4.2012,  09:18 Найти цитируемый пост)
блокировку через lock я ставлю

Нет, но не переусердствуй с lock-ами. Вообще старайся сводить их количество к необходимому минимуму.


Цитата(shtuceron @  13.4.2012,  09:18 Найти цитируемый пост)
И еще вопрос, в классе (одиночка) у меня реализованы события, нужно ли для каждого потока создавать события, которые потоки будут обрабатывать? или достаточно в главном потоке определить события?

Не понял вопроса.

Автор: shtuceron 13.4.2012, 11:28
Цитата

Встречный вопрос. Какая реализация?
Ленивая инициализация НЕ потокобезопасна, но защищать инициализацию через lock идея не из лучших, лишний lock при каждом обращении. Лучше инициализировать в основном потоке, а потом спокойно использовать.


Так я и делаю, инициализация проходит в основном потоке. Но если мы используем скажем TCP/IP соединение в разных потоках может возникнуть ситуация одновременной отправки сообщений - следовательно может возникнуть конфликт. Или я не прав?

Про события - самые обычные event-ты (например: пришел ответ от сервера - ошибка - я вызываю этот event и он обрабатывается в том потоке, который его реализует)... Если я в разных потоках попытаюсь реализовать события

Код

example.VSErrorEvent += new Singleton.VSErrorDelegate(OnVSError); (в двух потоках их объявил, ну функционал обработки ошибок разный)


Они и будут выполняться в разных потоках именно 2 события или только одно события в том потоке который сейчас активен?

Автор: azesmcar 13.4.2012, 11:35
Цитата(shtuceron @  13.4.2012,  11:28 Найти цитируемый пост)
Но если мы используем скажем TCP/IP соединение в разных потоках может возникнуть ситуация одновременной отправки сообщений - следовательно может возникнуть конфликт. Или я не прав?

Если сам класс соединения не обеспечивает безопасность - тогда может. smile 

Цитата(shtuceron @  13.4.2012,  11:28 Найти цитируемый пост)
я вызываю этот event

Обрабатывается он в том потоке, из которого вызываешь.

Автор: jonie 17.4.2012, 20:08
вот тут неплохая дока по теме http://www.yoda.arachsys.com/csharp/singleton.html
я только замечу проблему, описанную там отдельно:
Код

!!!!! // Bad code! Do not use! !!!!!!
public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                lock (padlock)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

почитайте..

Автор: azesmcar 17.4.2012, 21:53
jonie

Это же http://en.wikipedia.org/wiki/Double-checked_locking. Хотя я далеко не любитель этого патерна, тем не менее в .NET этот код рабочий. Модель памяти .NET гарантирует, что любая атомарная операция и любой lock - full memory fence. В данном случае lock (padlock) - это барьер и код вполне рабочий.
А почитать стоит smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)