powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Потокобезопасный singleton от Ninject
32 сообщений из 32, показаны все 2 страниц
Потокобезопасный singleton от Ninject
    #39590220
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет, есть необходимость создать потокобезопасный синглтон, чтобы можно было менять в нем данные из разных потоков. К сожалению в документации не нашел 100% ответ будет ли он безопасный в зависимости от разных условий инициализаций. Попытался сам проверить потокобезопасность следующими тестами.

Код: c#
1.
2.
3.
4.
5.
6.
// класс, который должен быть одиночкой

 public class DataStore
    {
        public string Name { get; set; }
    }



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
Kernel.Bind<DataStore>().ToSelf().InSingletonScope();
//thread-safe Tests

         (new System.Threading.Thread(() =>
            {
                DataLayer.DataStore r1 = ioc.Ioc.Get<DataLayer.DataStore>();
                r1.Name = "From BackgroundThread";
                Debug.WriteLine(r1.Name);
            })).Start();

            DataLayer.DataStore r = ioc.Ioc.Get<DataLayer.DataStore>();
            r.Name = "FromMainthread";
            Debug.WriteLine(r.Name);
//output
//FromMainthread
//FromMainthread
/////////////////////////////////

// те же самые тесты
 Kernel.Bind<Lazy<DataStore>>().ToConstant(new Lazy<DataStore>(
() => new DataStore()
)).InThreadScope();

//From BackgroundThread
//Поток 0x3714 завершился с кодом 0 (0x0).
//FromMainthread

/////////////////////////////////

 Kernel.Bind<DataStore>().ToSelf().InSingletonScope();

//FromMainthread
//FromMainthread



Вопрос- позволяет ли данные второго теста (Kernel.Bind<Lazy<DataStore>>().ToConstant(new Lazy<DataStore>(
() => new DataStore()
)).InThreadScope();) утверждать, что синглтон потокобезопасен?
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590278
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,
Объект безопасный, если все его поля до пятого колена безопасны.
Вывод, бери безопасные коллекции.....типа ConcurrenrDictionary.
Но у меня иногда и это глючит без блокировки.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590307
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Под потокобезопасностью синглтона подразумевается не потокобезопасность его методов или состояния, а потокобезопасное создание экземпляра синглтона ( см. у Скита ). То, что некий класс является [потокобезопасным] синглтоном, и то, что его свойства/методы потокобезопасны - вещи ортогональные.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590308
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и синглетон не имеет отношения к сабжу.
Синглетон - экземпляры, а ThreadSafe - доступ.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590309
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,
Спс за ссылку.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590311
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,
У меня список для потокового доступа просто находится рядом с главной формой ГУИ. И не надо синглетона).
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590373
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныПод потокобезопасностью синглтона подразумевается не потокобезопасность его методов или состояния, а потокобезопасное создание экземпляра синглтона ( см. у Скита ). То, что некий класс является [потокобезопасным] синглтоном, и то, что его свойства/методы потокобезопасны - вещи ортогональные.

Я не спец в ninject, но, думаю, что как и всякий приличный DI-контейнер, он должен обеспечить безопасное создание синглетона из коробки без всяких дополнительных телодвижений.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590375
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ninject в глаза не видел, так что могу наврать.
InThreadScope по идее указывает на то, что на каждый поток будет создан свой экземпляр "синглтона", т.е. сам класс объекта может быть и не потокобезопасным и у каждого потока будет свой DataStore и своё значение свойства Name.
Если делать Lazy прям синглтон, что один для всех, то:
Класс Lazy, согласно msdn является потокобезопасным, но вот сам DataStore таким не является.
как-то так получается:
Код: c#
1.
2.
3.
var lazy = Kernel.Get<Lazy<DataStore>>(); // норм
var ds = lazy.Value; // норм
ds.Name = ...; // не норм, если операция не будет атомарной, если в set'тер будет добавлена какая-то валидация, например.


В общем, Lazy ничего не даёт и не нужен тут. Ninject и сам по сути роль Lazy выполняет. DataStore конкретно в данном случае синхронизировать не нужно, т.к. на каждый поток будет свой экземпляр. Если прописать InSingletonScope(), тогда и DataStore нужно thread-safe'ить.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590405
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4koff,
на lazy не стоит заострать внимание-он просто делает отложенную инициализация, на потокобезопасность никак не влияет.
Стандартно советуют делать синглтон с lock для поткобезопасности, но он расточителен по ресурсам.
Еще метанит приводит такой пример потокобезопасного синглтона без лока
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
public class Singleton
{
    private static readonly Singleton instance = new Singleton();
 
    public string Name { get; private set; }
 
    private Singleton()
    {
        Name = System.Guid.NewGuid().ToString();
    }
 
    public static Singleton GetInstance()
    {
        return instance;
    }
}

только не очень понятно как Guid сделает его потокобезопасным.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590409
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_subСтандартно советуют делать синглтон с lock для поткобезопасности, но он расточителен по ресурсам.
Еще метанит приводит такой пример потокобезопасного синглтона без лока

Я вообще не понимаю - кому в наш век повсеместного DI может понадобиться писать свой синглтон.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590411
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub, под потокобезопасным синглтоном понимают то, что при получении объекта из разных потоков будет получен один и тот же объект. Это не значит что сам объект потокобезопасен, а только то, что можно одновременно вызвать метод:
Код: c#
1.
Singleton.GetInstance()


и получить один и тот же объект.
В примере guid используется чисто для проверки. Типа можно запустить кучу потоков, в них выполнить:
Код: c#
1.
Console.WriteLine(Singleton.GetInstance().Name);


и получить одну и ту же строку.
Потокобезопасность синглтона там реализуется за счёт статического readonly члена класса со всеми вытекающими плюсами и минусами.
При работе с такими "потокобезопасными" синглтонами нужно просто помнить и о потокобезопасности самого объекта, тут обезопасили только метод Singleton.GetInstance() и не более того.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590413
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_subСтандартно советуют делать синглтон с lock для поткобезопасности, но он расточителен по ресурсам.

Даблчек-лок практически не даст оверхеда, разве что кроме первого вызова.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590415
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
string потокобезопасен поэтому твоя обертка на над ним тоже потокобезопасна.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590416
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat, я вообще думал, что синглтоны уже несколько лет как перевели в антипаттерны :)
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590422
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4kofffkthat, я вообще думал, что синглтоны уже несколько лет как перевели в антипаттерны :)+1
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590426
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4kofffkthat, я вообще думал, что синглтоны уже несколько лет как перевели в антипаттерны :)

Да херь все это от Башни Слонячей Кости. Точно так же можно сказать, что конструктор это антипаттерн, а использовать надо только фабрики, а еще лучше абстрактные фабрики. К тому же я уже вообще и забыл, как объекты руками создавать - у нас везде когда что-то надо, то добавляешь в конструктор, а IoC сам туда всунет что нужно - синглтон там или не синглтон, или даже вообще какой-то обьект в другом процессе - меня, как его потребителя, это вообще не парит - это забота того, кто контейнер конфигурирует и самого контейнера.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590427
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
 public class DataStore
    {
public ObservableCollection<FakeClass> FakeList { get; set; }
    }


то есть если я предполагаю, что FakeList будет редактироваться из разных потоков, и я не хочу, чтобы какие- либо изменения пропали мне нужно искать Thread-Safe ObservableCollection<T> обертку?
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590430
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_subто есть если я предполагаю, что FakeList будет редактироваться из разных потоков, и я не хочу, чтобы какие- либо изменения пропали мне нужно искать Thread-Safe ObservableCollection<T> обертку?

Да. Использовать ReaderWriterLock или ReaderWriterLockSlim.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590432
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,

По хорошему, надо не допускать редактирования ресурса из разных потоков.
Нарезать куски работы для каждого потока - вот такой хайп параллельности.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590448
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat, это всё из-за модников-неучей. Сначала лепили статические классы. Потом начали задумываться о времени жизни объектов, о реализации интерфейсов и т.д. и т.п. и ломанулись использовать синглтон, типа это такая серебряная пуля, всем и всегда поможет. Статикам табу, синглтонам - милости просим. Потом опять голову включили и оказалось, что у синглтонов тоже не всё круто. Теперь им табу, а на коне всякие DI и сотоварищи.
По факту просто всему своё место. И статические классы норм и синглтоны и т.д. и т.п. Законодателям моды проще было сказать, что синглтоны не комильфо пользовать.

vb_sub, не забываем еще и про потокобезопасность FakeClass, если возможна работа с одним объектом коллекции из разных потоков.
Если разные потоки могут забрать один и тот же элемент коллекции и как-то его менять, тогда его внутренности тоже нужно защищать.
И всё равно там не всё так однозначно будет.
Типа напишете DataStore.Name = DataStore.Name + DataStore.Name
по отдельности всё безопасно, а в сумме одна большая беда.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590466
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_subPu4koff,
на lazy не стоит заострать внимание-он просто делает отложенную инициализация, на потокобезопасность никак не влияет.
вообще то в Lazy<T> реализована потоколбезопасность, по этому из 2 потоков получить 2 разных ленивых объекта не получится. https://referencesource.microsoft.com/#mscorlib/system/Lazy.cs,8b99c1f377873554, там даже в конструкторе есть параметр ThreadSafe
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590491
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4koffПотокобезопасность синглтона там реализуется за счёт статического readonly члена класса со всеми вытекающими плюсами и минусами.
Неправильно. Статическое readonly поле - всего лишь для хранения экземпляра, само по себе оно ничего не гарантирует, потокобезопасность там реализуется либо за счет вручную прописанных локов, либо за счет манпуляций с IL-флагом beforefieldinit , либо за счет обеспечивающих потокобезопасность классов FCL (Lazy<T>).
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590508
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныPu4koffПотокобезопасность синглтона там реализуется за счёт статического readonly члена класса со всеми вытекающими плюсами и минусами.
Неправильно. Статическое readonly поле - всего лишь для хранения экземпляра, само по себе оно ничего не гарантирует, потокобезопасность там реализуется либо за счет вручную прописанных локов, либо за счет манпуляций с IL-флагом beforefieldinit , либо за счет обеспечивающих потокобезопасность классов FCL (Lazy<T>).

Кури спеки. Инициализация статического поля компилятором помещается либо в начало существующего статического конструктора, либо, при отсутствии оного, в сгенерированный. Статический конструктор всегда вызывается в потокобезопасной манере - хоть сколько потоков одновременно обратятся к классу, статический конструктор вызовется только один раз, одним потоком и до выполнения любого кода того же класса. Т.ч. реализовывать синглтон через статическое поле это и есть самый эффективный и простой метод - а всё это дрочево с локами, двойной проверкой и проч. - это только чтобы джуниоров на интервью погномить.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590511
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныPu4koffПотокобезопасность синглтона там реализуется за счёт статического readonly члена класса со всеми вытекающими плюсами и минусами.
Неправильно. Статическое readonly поле - всего лишь для хранения экземпляра, само по себе оно ничего не гарантирует, потокобезопасность там реализуется либо за счет вручную прописанных локов, либо за счет манпуляций с IL-флагом beforefieldinit , либо за счет обеспечивающих потокобезопасность классов FCL (Lazy<T>).
так в этом и смысл синглтона, что там ровно один экземпляр. Ровно это и даёт статический член класса с инициализацией.
такой синглтон не потокобезопасный:
Код: c#
1.
2.
3.
4.
5.
6.
static A GetInstance()
{
  if (_instance == null)
    _instance = new A();
  return _instance;
}


если if обернуть в тот же lock, тогда уже типа будет потокобезопасный синглтон, но это не значит, что стал потокобезопасным возвращенный объект типа А.

при таком варианте:
Код: c#
1.
private static readonly Singleton instance = new Singleton();


невозможна же ситуация, что instance в разное время будет ссылаться на разные объекты или что инициализатор new Singleton() отработает несколько раз для разных потоков? А большего от синглтона и его потокобезопасности и не нужно.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590581
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthatКури спеки. Инициализация статического поля компилятором помещается либо в начало существующего статического конструктора, либо, при отсутствии оного, в сгенерированный. Статический конструктор всегда вызывается в потокобезопасной манере - хоть сколько потоков одновременно обратятся к классу, статический конструктор вызовется только один раз, одним потоком и до выполнения любого кода того же класса. Т.ч. реализовывать синглтон через статическое поле это и есть самый эффективный и простой метод - а всё это дрочево с локами, двойной проверкой и проч. - это только чтобы джуниоров на интервью погномить.
Кури человеческую реализацию паттерна. Инициализация поля экземпляра синглтона в статик-конструкторе в общем случае делает его не ленивым - см. выше про флаг beforefieldinit. Поскольку мало кто представляет все нюансы этого флага, то для перестраховки выносят инициализацию инстанса из статического инициализатора типа, и оборачивают в локи - так добиваются и ленивости, и потокобезопасности. Кто представляет - использует пустой статик-конструктор, и тоже не инициализирует инстанс в статическом конструкторе (т.к. мым можем в коде обратиться к константе класса синглтона, или к статик-методу, не связанному с инстансом - а у нас всё равно будет создан экземпляр).
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590584
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4koffА большего от синглтона и его потокобезопасности и не нужно.
Нужно. Обычно еще нужно, чтобы он был ленивым.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590603
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныPu4koffА большего от синглтона и его потокобезопасности и не нужно.
Нужно. Обычно еще нужно, чтобы он был ленивым.
Согласен. В основном из-за этого и стали мудрить с синглтонами, так бы и сидели на статических классах.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590609
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныИнициализация поля экземпляра синглтона в статик-конструкторе в общем случае делает его не ленивым

Это было до .NET 4 - в 4 поведение поменяли, и статические поля всегда инициализируются лениво.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590617
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4koffСогласен. В основном из-за этого и стали мудрить с синглтонами, так бы и сидели на статических классах.

Далеко не только из-за этого. В статическом классе нельзя использовать полиморфизм, наследование, отделить интерфейс от реализации и т.п.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590671
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,
Кроме того он сталкивает лбами 2е парадигмы - расшаривать(синглетон) и изолировать(потоки)
Поэтому и молчит про задачу)
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39590950
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthatСон Веры ПавловныИнициализация поля экземпляра синглтона в статик-конструкторе в общем случае делает его не ленивым

Это было до .NET 4 - в 4 поведение поменяли, и статические поля всегда инициализируются лениво.
Не всегда и не везде. Пример: https://codeblog.jonskeet.uk/2010/01/26/type-initialization-changes-in-net-4-0/ , код из подраздела "Lazy initialization: .NET 4.0". Если скомпилировать в MSVS 2017 в релизе, то вывод будет такой:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Before static method
In static method
Before construction
Before instance method
In instance method
Before static method using field
Type initialized
In static method using field
y = 0

- все вроде бы как положено, ленивая инициализация налицо. Но если собрать в дебаге, то вывод будет уже такой:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
Before static method
Type initialized
In static method
Before construction
Before instance method
In instance method
Before static method using field
In static method using field
y = 0

- ленивостью уже и не пахнет. И аналогичный результат будет, если код скомпилировать в MSVS 2010 SP 1 в любой конфигурации.
Плюс там же по ссылке см. приписку про implementation-specific in terms of the C# compiler (пример с CachingSideEffect). Дабы обезопасить себя от таких нюансов, люди и пишут синглтоны с использованием Lazy/beforefieldinit/локов.
...
Рейтинг: 0 / 0
Потокобезопасный singleton от Ninject
    #39591011
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

Ну х.з., выше уже говорили, что трудно представить ситуацию "не сыграл козырный туз":
Pu4koffпри таком варианте:
Код: c#
1.
private static readonly Singleton instance = new Singleton();


невозможна же ситуация, что instance в разное время будет ссылаться на разные объекты или что инициализатор new Singleton() отработает несколько раз для разных потоков? А большего от синглтона и его потокобезопасности и не нужно.
Пока статический конструктор не отработал, никто/ничто ведь не сможет использовать данный тип, верно? По завешению статического конструктора статическое поле будет гарантировано инициализированным.

По поводу ленивости, да. Однако, как правило, синглтоны используются в рантайме всегда (если нет, тогда и выбор синглтона - неудачное решение).
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Потокобезопасный singleton от Ninject
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]