Как на Delphi сделать потокобезопасный синглетон БЕЗ использования критических секций?
Ну скажем только с interlocked- операциями.
Но не так как TMonitor у Embarcadero.
У меня есть свой вариант, но я приведу его позже.
Есть такой эскиз:
(+) https://m.habrahabr.ru/post/147373/
Но там всё про C++ и C#.
Да ещё и со встроенным lock или static-переменой, которая удрвлетворяет "новому стандарту". Что по сути является критической секцией, только скрытой в потрохах языка.
А меня интересует Delphi. И БЕЗ критических секций и TMonitor.
Или всё проще и достаточно критической секции, но ОДНОЙ. ГЛОБАЛЬНОЙ. А как там с вероятностью deadLock'ов? Когда создаваемый синглетон в своём конструкторе обращается к другому синглетону, который ещё не создан.
Ну скажем только с interlocked- операциями.
Но не так как TMonitor у Embarcadero.
У меня есть свой вариант, но я приведу его позже.
Есть такой эскиз:
Var instance : TMyClass = nil; Lock : Integer = 0; // - это глобальные переменные Function getInstance: TMyClass; Var LockValue : Integer; // - это локальная переменная Begin If instance = nil then Begin LockValue := interlockedIncrement(lock); Try If lockValue = 1 then Begin If instance = nil then Instance := TMyClass.Create; End Else Begin While instance = nil do Sleep(0); End; Finally InterlockedDecrement(lock); End End Result := instance; Assert(Result <> nil); End;Покатить?
(+) https://m.habrahabr.ru/post/147373/
Но там всё про C++ и C#.
Да ещё и со встроенным lock или static-переменой, которая удрвлетворяет "новому стандарту". Что по сути является критической секцией, только скрытой в потрохах языка.
А меня интересует Delphi. И БЕЗ критических секций и TMonitor.
Или всё проще и достаточно критической секции, но ОДНОЙ. ГЛОБАЛЬНОЙ. А как там с вероятностью deadLock'ов? Когда создаваемый синглетон в своём конструкторе обращается к другому синглетону, который ещё не создан.
Почему без критической секции? Потому, что критическую секцию надо опять же где-то создать. Опять же - потокобезопасно. Ну или "заранее".
ОтветитьУдалитьЕсли бы я хотел с критической секцией - я бы даже не спрашивал.
Удалить> Почему без критической секции? Потому, что критическую секцию надо опять же где-то создать. Опять же - потокобезопасно. Ну или "заранее".
Удалить>
[1] Для синглтона - заранее. Хранить, например, в strict-private статическом поле класса, создавать в секции инициализации, контрольно освобождать - рядом, при финализации модуля.
После того, как объект построен, думаю, критическая секция уже ненужна, можно освободить сразу, если есть желание. Или использовать в целях реализации потокобезопасности самого класса, но тут вопрос спорный.
[2] Если накладные расходы на инициализацию синглетного класса минимальны (как у TUnicodeEncoding, например) его можно создавать безусловно, и условно, с сиспользованием InterlockedCompareExchangePointer освобождать, если объект уже построен (см. вариант 3 по ссылке ниже). По слухам такое можно встретить в VCL.
Неплохая подборка методов инициализации синглтона приводится здесь.
[3] "Ленивая" инициализация синглтона, действительно необходима не всегда. Возможно, будет проще вместо возни с критическими секциями, при инициализации модуля, гарантировано до появления нитей-пользователей построить сам синглтон. Но это уже зависит от архитектуры приложения, может оказаться, что такое не всем такое подойдёт: например, есть любители создавать нити при инициализации модуля.
Ну это всё я как раз-таки знаю
УдалитьИ то что данные синглетонов должны быть потокобезопасны - я понимаю. Но эту проблему я как раз таки давно решил.
УдалитьМне одному сложно читать с такой расстановкой пробелов?
ОтветитьУдалитьЭтот комментарий был удален автором.
УдалитьС телефона очень сложно нормально набрать. Компьютер - сломался. А на работе интернет - только по рабочим вопросам. Да и некогда.
УдалитьStimmt das?
Ого, набор кода на телефоне - то еще удовольствие. =\
Удалить;) да уж
Удалить