![]() |
Re: Viele Threads untereinander synchronisieren
also .. das Problem bei Threads ist eigentlich nur, dass ein Thread Daten schreibt, noch gar nicht fertig ist, und ein anderer Thread diese Daten schon liest, und dann "halb" richtige Daten liest.
Stell Dir einen Integer vor, der hat 32 Bit. also 4 Bytes. Ein Thread fängt jetzt an, diesen Integer von 4 Byte zu schreiben und ist gerade fertig geworden mit einem Byte. (Auch wenn es nur ein Befehl in Delphi ist, sind es unter umständen mehrere Befehle in Assembler für den Prozessor) Wenn jetzt gerade in dem Moment ein anderer die Daten liest, dann liest er 4 Byte. Ein Byte ist schon aktuell, die anderen 3 Byte sind noch irgendwelcher Quatsch, der vorher drin war. Jetzt liest er einen völlig anderen Integer, als gewollt. Es soll Quelltext geben, die mit ungültigen Daten schlecht klar kommen und dann Exceptions verursachen :-) Deswegen darf das Schreiben von Daten immer nur hintereinander geschehen. Und von einem Thread ! Da es verschwendung wäre, Daten nur hintereinander zu lesen, dürfen also beim Lesen auch beliebig viele Threads auf Daten zugreifen. Es muss nur sicher gestellt werden, dass gerade niemand schreibt in dieser Zeit. Deswegen gibt es auch das lustige Object, dass früher mal Borland für Dich programmiert hat, mit dem lustigen Namen "TMultiReadExclusiveWriteSynchronizer" Eine kleine Ausnahme sind Datentypen, die nur ein Byte benötigen. das Macht der Prozessor in einem Rutsch, da kann auch niemand dazuwischenfunken ... das muss nicht syncrhonisiert werden... der Prozessor liest Byteweise, nicht Bitweise .. Zitat:
kannst Du denn etwas Code posten? wo liegen jetzt die Daten, auf die beide Threads gleichzeitig schreiben und lesen könnten? Geschieht diese über "zentrale" Schreib und Lesefunktionen. Wenn Du natürlich Globale Daten hast, auf die beide Threads zugreifen (auch den Hauptthread nicht vergessen, das ist auch einer) dann musst Du auch ein globales Syncobject einführen ... Wenn Du das lesen und schreiben allerdings an zentraler Stelle machst und alle Threads nur diese Funktionen aufrufen, dann nur dort . |
Re: Viele Threads untereinander synchronisieren
Okay... Also das Zwischenobjekt ist in etwas so definiert:
Delphi-Quellcode:
Die Threads sehen in etwa so aus:
TConnection = class
private owner: TWThread; weight: Double; public constructor Create(aOwner: TWThread;aConn: TWThread); procedure ProcessSignal(); end; procedure TConnection.ProcessSignal; begin owner.ReceiveSignal; Inc(weight); end;
Delphi-Quellcode:
TWThread = class(TThread)
private value: Integer; public constrctor Create; procedure CreateConnection(target: TWThread); function ReceiveConnRequest(link: TWThread): TConnection; procedure ReceiveSignal; procedure Execute();override; end; procedure TWThread.CreateConnection(target: TWThread); begin connectionList.Add(target.ReceiveConnRequest(self)); end; function TWThread.ReceiveConnRequest(link: TWThread): TConnection; begin Result:=TConnection.create(self,link); ownedConns.Add(Result); end; procedure TWThread.Execute(); begin while not Terminated do begin if berechnungen_moeglich then begin rechnen; irgendwann do connectionList[item].ProcessSignal; end else Suspend; end; procedure TWThread.ReceiveSignal; begin Inc(value); if Suspended then Resume; end; Zitat:
Ist vielleicht jetzt etwas klarer... |
Re: Viele Threads untereinander synchronisieren
Zitat:
und wann wie wo wer was nutzt. es gibt auch eine Threadsichere TList, namens "TThreadList ", wenn es sich bei den "gemeinsam genutzten Daten um eine TList handelt. da kann man sich critical Sektions sparen und die Liste "locken" und "unlocken" hab ich aber noch nie verwendet .. hab meine erklärung nochmal bissl verändert. Eigentlich müsste das weitere Vorgehen damit jetzt klar sein, nur Du kennst Dein Anwendung ... Zitat:
somit ergibt sich ein neues Problem .. die VCL ist nicht threadsicher .. das heißt .. Kommunikation mit der GUI nur über die nicht ganz optimale Synchronize Funktion ..... da bleibt Dir leider nix anderes übrig .. |
Re: Viele Threads untereinander synchronisieren
Zitat:
Wann wo wie welcher Thread daten nutzt ist aber wirklich unmöglich vorherzusagen. Es hängt von einem Threadinternen wert ab, der in Execute() bearbeitet wird, ob Thread1 ein Signal über das Linkobjekt an Thread2 sendet. Wie benutze ich das TMultiReadExclusiveWriteSynchronizer? (wer hat sich den diesen sperrigen Namen ausgedacht?) |
Re: Viele Threads untereinander synchronisieren
isch mach Dir mal ein Beispiel.
Zitat:
aber warte mal 5 Minuten ... |
Re: Viele Threads untereinander synchronisieren
Delphi-Quellcode:
Der TMultiReadExclusiveWriteSynchronizer macht nur bei großen Datenmengen Sinn, bei einzelnen Integern ist der etwas Oversized ...
Wie benutze ich das TMultiReadExclusiveWriteSynchronizer? (wer hat sich den diesen sperrigen Namen ausgedacht?)
Die Klasse erlaubt das gleichzeitige Lesen von Daten von mehreren Threads, sofern gerade kein Thread schreibt, stellt aber sicher, dass wenn geschrieben wird, alle anderen schreibenden und lesenden Threads blockiert werden ... |
Re: Viele Threads untereinander synchronisieren
Wow! Ich habe jetzt mal die entsprechenden Stellen mit CriticalSections geschützt und - voilà, seit 2 Minuten keine Fehler mehr!
Hoffentlich bleibt das so... Aber schonmal vielen Dank! :thumb: Sieht bis jetzt super aus! EDIT: Zu früh gefreut... Ich bekomme wieder SIGFPEs ohne Backtrace... Der Fehler kann aber überall anders auch liegen. Ich schaue mir das nochmal genauer an. |
Re: Viele Threads untereinander synchronisieren
Zitat:
zu beachten ist allerdings, dass nur die Execute Methode im Thread läuft. alle anderen Funktionen laufen im Hauptthread .. es sei denn , sie werden von Execute Aufgerufen. Datenzugriffe in einer THread Klasse können also dennoch von unterschiedlichen Threads aufgerufen werden ... Was zu beachten wäre ... Zitat:
|
Re: Viele Threads untereinander synchronisieren
So, jetzt läuft wirlich alles! Die verbelibenden Fehler hatte alle mit der grafikbibliothek Qt4 zu tun und sind jetzt behoben. Ein "CriticalSection" in den Zeichenfunktionen hat sich dabei als sehr sinnvoll herausgestellt, obwohl da nur gelesen wird. (Aber wenn man versucht, was zu lesen was nicht existiert ist das halt ein Problem...)
Nochmals vielen Dank! :bounce1: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:58 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