![]() |
Implementierung TSingleton für thread-safety (z.B. Spring4D)
Hallo zusammen,
ich beschäftige mich gerade mit Singletons, und es wird üblicherweise das Erzeugen mit CS abgesichert, so wie hier in ![]()
Delphi-Quellcode:
Die eigentliche zu kapselnde Klasse <T> muss aber auch threadsicher sein, wenn da mehrere Threads global drauf zugreifen können.
class function TSingleton.GetInstance<T>: T;
begin if not Assigned(TSingleton<T>.fInstance) then begin fCriticalSection.Enter; try if not Assigned(TSingleton<T>.fInstance) then TSingleton<T>.fInstance := T.Create; finally fCriticalSection.Leave; end; end; Result := TSingleton<T>.fInstance; end; Ich frage mich ob man dafür in einfachen Fällen nicht die bereits bestehende Instanz von fCriticalSection nehmen könnte / sollte. So sparte man zumindest unnötige CS-Ressourcen in der zu kapselnden Klasse ein. Das entspräche womöglich nicht einer optimalen Trennung der "Concerns", aber könnte doch die Ressourcen und Performance optimieren. Die zu kapselnde Klasse könnte für den Fall von einer speziellen Klasse abgeleitet sein, z.B. type T = class; für alle nicht sicheren Fälle wie bisher, type T = class(TSingletonThreadsafe); Abhängig von dem Type der Klasse könnte dann die CS im Create( FCriticalSection ); übergeben werden. Oder spricht etwas Grundsätzliches dagegen, und es gäbe es sinnvollere Möglichkeiten das Konstrukt threadsafe zu machen ? |
AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
Vielleicht verstehe ich Deine Frage nicht richtig, aber
Die Klasse die Erzeugt wir muss nicht threadsicher sein, sondern nur die Create Methode Reentrant. Also "nur" erzeugen und initialisieren und nix weiter im Create machen. Dann nutze ich
Delphi-Quellcode:
um die neue Instance der eigentlichen zuzuweisen.
TInterlocked.CompareExchange<T>
So mache ich es jedenfalls in allen Threads des FDK. Hatte hiermit noch nie ein Problem. Grüsse und schönes Ostern Mavarik :coder: |
AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
Früher gab es
![]() ![]() das kapselte Delphi dann mal als ![]() aber man darf auch gern das neuere multi-platforme ![]() Jo, schauen ob leer, wenn ja, dann erstellen, die Referenz threadsicher eintragen/austauschen, was mit einer atomaren Operation am Einfachsten geht (Interlocked, Atomic oder LOCK im Assembler) und wenn nicht erfolgreich, dann die Instanz wieder freigeben. (falls ein anderer Thread das gleichzeitig gemacht hatte und schneller war)
Delphi-Quellcode:
if not Assigned(XXX) then begin
NEW := TIrgendwas.Create; if AtomicCmpExchange(XXX, NEW, nil) <> nil then NEW.Free; end; XXX.DoSomething; |
AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
Ja genau, für das eigentliche Erzeugen der Instanz gibt es diese Methoden.
Was ich meine ist aber, das die erzeugte Klasse im Singleton auch ThreadSicher sein muss. Je nachdem hat diese ja noch globale Felder zu verwalten. TSingleton<TKlasse> Um diese abzusichern könnte man doch das globale CS des TSingletons wieder-verwenden, und an die erzeugte Instanz im Create der TKlasse übergeben. Macht das Sinn, oder sollte TSingleton und TKlasse jeweils ihr eigenes CS haben und verwalten ? Ich weiss das man generell besser die Klassen trennen sollte, Aber in diesem Fall macht TKlasse ja nur im TSingleton Sinn. Also könnten hier Ressorcen optimiert werden, weil TKlasse nie allein verwendet wird. |
AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
Zitat:
Ob ich ein ode zwei Mutexe, Kritische Abschnitte oder Monitore benutze ist doch nun wirklich zu vernachlässigen. |
AW: Implementierung TSingleton für thread-safety (z.B. Spring4D)
Der Mehrwert wäre das die TKlasse eine CS per DI übergeben bekäme, und sich nicht selber drum kümmern muss.
Allerdings ist TKlasse ja selber ein Singleton, insofern hast du Recht. Deshalb frage ich mich was hier wohl der bessere Weg wäre. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz