Delphi-PRAXiS
Seite 4 von 4   « Erste     234   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Critical Section um globale Methode? (https://www.delphipraxis.net/192619-critical-section-um-globale-methode.html)

SneakyBagels 7. Jun 2017 18:02

AW: Critical Section um globale Methode?
 
Zitat:

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.
Danke! Muss ich heute Abend noch einmal ausführlich testen!

Wenn BeginRead nur dafür da ist zu verhindern, dass kein Write ausgeführt werden kann, lasse ich das vermutlich weg denn es gibt genau eine einzige Stelle an der geschrieben wird.

jaenicke 7. Jun 2017 19:50

AW: Critical Section um globale Methode?
 
Zitat:

Zitat von SneakyBagels (Beitrag 1373766)
Wenn BeginRead nur dafür da ist zu verhindern, dass kein Write ausgeführt werden kann, lasse ich das vermutlich weg denn es gibt genau eine einzige Stelle an der geschrieben wird.

Entweder du kannst sicherstellen, dass bei dem Schreibvorgang ohnehin niemand liest, dann brauchst du keinerlei Sperren (sofern beim Lesen alles threadsicher ist).

Oder du kannst nicht ausschließen, dass jemand liest während du schreibst, dann musst du dies durch Sperren sicherstellen, in dem Fall durch den TMultiReadExclusiveWriteSynchronizer. Dann musst du dem aber auch sagen wann du lesen und wann schreiben möchtest, damit er diese Sperre auch durchführen kann.

SneakyBagels 7. Jun 2017 20:06

AW: Critical Section um globale Methode?
 
Ist bei mir ganz einfach: es ist exakt eine einzige Zeile Code im Multithread-System, die schreibenden Zugriff hat.
Es gibt eine weitere solche Zeile, die hat aber nichts mit Multithreading zu tun.

Es ist egal von wo aus ich TMultiReadExclusiveWriteSynchronizer aufrufe, oder muss das aus dem Thread heraus sein der schreiben möchte?

jaenicke 8. Jun 2017 05:45

AW: Critical Section um globale Methode?
 
Zitat:

Zitat von SneakyBagels (Beitrag 1373775)
Es ist egal von wo aus ich TMultiReadExclusiveWriteSynchronizer aufrufe, oder muss das aus dem Thread heraus sein der schreiben möchte?

Ich glaube ich hole besser noch einmal weiter aus bevor ich das beantworte.

Du musst vor jedem Schreibvorgang BeginWrite aufrufen (ab da werden alle Schreib- und Lesezugriffe blockiert) und nach dessen Abschluss EndWrite (dann können wieder alle lesen).

Vor jedem Lesevorgang musst du BeginRead aufrufen (ab da wartet BeginWrite, falls es danach aufgerufen wird, auf den Abschluss des Lesevorgangs) und nach dessen Abschluss EndRead (danach kehrt BeginWrite zurück, falls es nach BeginRead aufgerufen wurde.

Auf diese Weise kann ein Schreibvorgang erst nach Abschluss aller laufenden Lesevorgänge passieren und neue Lesevorgänge erst nach dem Abschluss eines laufenden Schreibvorgangs.
Solange aber niemand schreibt, können alle parallel lesen, d.h. BeginRead..EndRead kann beliebig parallel laufen.

Um zur Frage zurückzukommen:
Im Prinzip ist es egal aus welchem Threadkontext du BeginWrite..EndWrite aufrufst solange es vor bzw. nach dem Schreibvorgang passiert. Wann der passiert, sollte ein anderer Thread aber in der Regel (es gibt Ausnahmen, ja) gar nicht kontrollieren, weshalb die praktische Antwort meistens Nein ist, auch wenn es technisch egal ist.

Genau lässt sich das aber nur sagen, wenn man den konkreten Ablauf kennt. Es würde auch abstrakt ohne Code genügen, z.B. auch als Diagramm, wer (Thread XY) wann (während andere Threads laufen? autark? kontrolliert durch einen anderen Thread? ...) was (Schreiben oder Lesen) macht, um einen Überblick zu haben.

HolgerX 8. Jun 2017 08:32

AW: Critical Section um globale Methode?
 
Hmm..

Der Zugriff erfolgt vergleichbar einer TCriticalSection.

Beispiel:

Delphi-Quellcode:
unit Unit2;

interface

uses
  SysUtils;

function LeseDaten : string;
procedure SchreibeDaten(Value : string);

implementation

var
  MSync_Global : TMultiReadExclusiveWriteSynchronizer;

  Daten_Test : string;

function LeseDaten : string;
begin
  MSync_Global.BeginRead;
  try
    Result := Daten_Test;
  finally
    MSync_Global.EndRead;
  end;
end;

procedure SchreibeDaten(Value : string);
begin
  MSync_Global.BeginWrite;
  try
    Daten_Test := Value;
  finally
    MSync_Global.EndWrite;
  end;
end;

initialization
  MSync_Global := TMultiReadExclusiveWriteSynchronizer.Create;

finalization
  MSync_Global.Free;

end.

Alle Threads (auch der Main..) nutzen nun einfach

function LeseDaten : string;
procedure SchreibeDaten(Value : string);

für den Zugriff auf 'Daten_Test : string;'.

Durch die Verwendung des globalen 'MSync_Global : TMultiReadExclusiveWriteSynchronizer;' innerhalb der Funktionen ist der Zugriff Threadsave.. ;)

(Einfach nur mal so Runtergeschrieben als minimales Beispiel ;) )
(Fehler und Irtümer nicht ausgeschlossen ;) )

SneakyBagels 8. Jun 2017 09:59

AW: Critical Section um globale Methode?
 
Zitat:

Zitat von jaenicke (Beitrag 1373780)
Genau lässt sich das aber nur sagen, wenn man den konkreten Ablauf kennt. Es würde auch abstrakt ohne Code genügen, z.B. auch als Diagramm, wer (Thread XY) wann (während andere Threads laufen? autark? kontrolliert durch einen anderen Thread? ...) was (Schreiben oder Lesen) macht, um einen Überblick zu haben.

Wie eine Seite zuvor beschrieben, hier mit Pseudo-Code.


Delphi-Quellcode:
// Andere Unit erzeugt die Threads aus dem Mainthread heraus
erzeuge Thread 1+2+3 und gebe jedem ein Teil aus einer großen Liste; // (ja ich weiß, es gibt TParallel.For :P )


// Die Thread-unit selber
-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;
Wie man sieht gibt es genau eine einzige Stelle in dieser Thread-Unit, wo geschrieben wird. Alles danach ist nur noch lesen.

HolgerX 8. Jun 2017 14:54

AW: Critical Section um globale Methode?
 
Zitat:

Zitat von SneakyBagels (Beitrag 1373814)
Delphi-Quellcode:
// Andere Unit erzeugt die Threads aus dem Mainthread heraus
erzeuge Thread 1+2+3 und gebe jedem ein Teil aus einer großen Liste; // (ja ich weiß, es gibt TParallel.For :P )


// Die Thread-unit selber
-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;
Wie man sieht gibt es genau eine einzige Stelle in dieser Thread-Unit, wo geschrieben wird. Alles danach ist nur noch lesen.


Um das Sync zu machen, musst du dennoch von jedem Lesen 'BeginRead' und danach 'EndRead' machen! Nur fürs Schreiben BeginWrite/EndWrite reicht nicht!


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:41 Uhr.
Seite 4 von 4   « Erste     234   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz