![]() |
AW: Critical Section um globale Methode?
Zitat:
Ist wie der unterschied zwischen
Delphi-Quellcode:
und
StringList[123]
Delphi-Quellcode:
.
StringList.Strings[123]
Abgesehn, dass TMonitor was "Eigenes" ist und TCriticalSection die API vom Windows kapselt, aber von der Funktion her sind die schon vergleichbar. |
AW: Critical Section um globale Methode?
Ok dann bleibe ich wohl bei CriticalSections.
Die sind mir vom Aufbau her so oder so logischer. Ich selber konnte bei meinen Tests keinerlei Performanceunterschied feststellen. Scheinen wohl nur Nanosekunden zu sein. |
AW: Critical Section um globale Methode?
In Delphi gibt es noch viel mehr Implementationen, die das Gleiche wie eine CriticalSection/TMonitor erledigen.
Dann noch paar Dinger mit Zusatzfunktionen, wie z.B. den TMultiReadExclusiveWriteSynchronizer (TMREWSync), welcher parallele Lesezugriffe erlaubt und nur bei einem Schreibzugriff alles komplett sperrt. Und für Zugriffe auf einzelne Interger, Pointer, Booleans und anderen Kleinkram gibt es mehrere Interlocked-Implementationen, welche atomare Schreibzugriffe ermöglichen. |
AW: Critical Section um globale Methode?
Zitat:
Aber heißt das jetzt, dass sobald ich bei Verwendung von TMultiReadExclusiveWriteSynchronizer irgendwo trotzdem schreibe, nur dieser eine schreibende Zugriff geblockt wird? Wenn ja dann wäre das ja ein recht großer Vorteil denn statt 100 von 100 "Dingern" zu blocken (wo ich 1x schreibe und 99x lese) würde hier nur 1x geblockt. Sehe ich das richtig? Dass ich schreibenden Zugriff hier mit BeginWrite und EndWrite absichern muss ist klar. Aber wofür den lesenden? Edit: durch die Verwendung eines globalen TMultiReadExclusiveWriteSynchronizer und BeginWrite/EndWrite, welches ich NUR dort verwende wo ich meiner Klasseninstanz Daten zuweise, ist meine Prozedur rund 5% schneller geworden. Kann das daran liegen, dass ich nun nicht mehr rigoros alles blockiere sondern nur noch den schreibenden Zugriff? |
AW: Critical Section um globale Methode?
Zitat:
Delphi-Quellcode:
ist für solche Szenarien besser geeignet, als
TMultiReadExclusiveWriteSynchronizer
Delphi-Quellcode:
oder
TCriticalSection
Delphi-Quellcode:
. Solange jetzt n-Threads gleichzeitig NUR lesen, wirst du einen Performancevorteil feststellen können. Im Grunde stellt der
TMonitor
Delphi-Quellcode:
jetzt nur noch sicher, dass erst alle lesenden Zugriffe abgeschlossen sind, bevor ein schreibender Zugriff stattfindet und blockiert während dieser Zeit dann alle lesenden Operationen (deshalb musst du trotzdem signalisieren, an welchen Stellen du lesen willst).
TMultiReadExclusiveWriteSynchronizer
Mit
Delphi-Quellcode:
oder
TCriticalSection
Delphi-Quellcode:
hingegen, kann auch nur ein einziger Thread gleichzeitig lesen.
TMonitor
|
AW: Critical Section um globale Methode?
Lesezugriffe sperren sich nicht gegenseitig ... mehrere sind erlaubt.
So lange es Lesesperren gibt, warten alle Schreibanfragen. Eine Schreibsperre sperrte alle anderen Lese und Schreibzugriffe. Natürlich nur verwendbar für "echte" Lesezugriffe, wo wirklich nichts geschrieben wird. z.B. Stream.Read ist zwar ein Lesezugriff, aber da bei wird der Positionszeiger geändert, was einen Schreibzugriff darstellt. Aber sonst können mehrere ungehindert gleichzeitig lesen und wenn Einer was schreiben will, dann ist so lange alles gesperrt. MultiReader ist demnach besonders hilfreich, bei vielen Lesezugriffen und seltenen Schreibzugriffen. Bei der CriticalSection und dem TMonitor ist immer alles gesperrt, egal ob lesen oder schreiben. (nur Zugriffe aus dem selben Thread sind erlaubt, da sie per se threadsave sind und man so keinen Deadlock riskiert, wenn man in einem Thread verschachtelt Enter aufruft) |
AW: Critical Section um globale Methode?
Mhhh ok das heißt also
Delphi-Quellcode:
So habe ich das aktuell. Jeder Thread kann der globale Klasseninstanz ein Item zuweisen. An anderen Stellen (nicht in diesem Thread) lese ich die Klasseninstanz dann aus und zeige die dahinterliegenden Daten auf der Benutzeorberfläche an.
-thread-instanzen 1+2+3 (alle selber Code, nur unterschiedliche Listen sind abzuarbeiten)
begin schleife anfang _globals.aMultiReadExclusiveWriteSynchronizer.BeginWrite; setze globale Klasseninstanz := Liste.Items[i] _globals.aMultiReadExclusiveWriteSynchronizer.EndWrite; (a) ... lese hier ... lese dort ... lese nochmals hier (b) schleife ende end; Ist das so richtig oder müsste ich jetzt noch zusätzlich von (a) bis (b) ein _globals.aMultiReadExclusiveWriteSynchronizer.Begi nRead; und EndRead setzen? |
AW: Critical Section um globale Methode?
Dort, wo lesend auf globale-Klasseninstanz zugegriffen wird, kommt natürlich ein BeginRead drumrum.
Erstmal reicht es den Lese-Zugriff auf diese Variable zu sperren, aber wenn sich innerhalb dieser Instanz auch etwas ändern kann (Property und enthaltene Variablen), dann auch das mit einschließen. Wenn sich an der Objektinstanz nicht gleichzeig in mehreren Thread was ändert, also z.B. da was einstellen, dann die Variable setzen und jemand Anderes liest dann nur diese Variable, oder holt sich sie da raus (auslesen und NIL setzen), dann kann man auch mit InterlockedExcange oder den neuen TLock-irgendwas-Klassen in der System-Unit arbeiten. |
AW: Critical Section um globale Methode?
Da achte ich strikt drauf. Erst ändere ich und dann lese ich. Danach wird erstmal nicht mehr geändert. Im jedem Schleifendurchgang gibt es nur eine einzige Änderung.
Wofür ist es denn wichtig den lesenden Zugriff zu sperren? Wenn man 5 Thread-Instanzen hat, alle haben die gleichen Dinge abzuarbeiten, man aber den lesen Zugriff blockieren muss, kann man dann hier überhaupt noch von Multithreading reden? Erste Tests zeigen, dass wenn ich überall den lesenden Zugriff blockiere der Code doppelt so lange braucht als vorher. Den lesenden Zugriff hatte ich früher noch nie blockiert, immer nur den schreibenden. |
AW: Critical Section um globale Methode?
Die Lesedinge sperren sich dabei nicht gegenseitig.
Das BeginRead ist nur dafür da, um zu verhindern, dass jemand während des Lesens etwas ändern kann. BeginRead sperrt das BeginWrite, bzw. hält selber an, wenn gerade geschrieben wird. Andere BeginRead werden aber durch den Read-Lock (durch BeginRead) nicht beeinflusst. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:01 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-2025 by Thomas Breitkreuz