AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
Thema durchsuchen
Ansicht
Themen-Optionen

Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

Ein Thema von Mavarik · begonnen am 2. Jul 2014 · letzter Beitrag vom 6. Jul 2014
Antwort Antwort
Seite 3 von 5     123 45      
Mikkey

Registriert seit: 5. Aug 2013
265 Beiträge
 
#21

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 3. Jul 2014, 13:46
Ich glaube nicht, dass die Spekulation über atomare Instruktionen in Bezug auf die gestellte Frage Sinn macht.

In DP geht es im Wesentlichen um Delphi, also um eine Hochsprache, die Umgebung sollte man generell als Black Box betrachten.

Somit kann man definieren:

Zitat:
Ein System (Programm) ist thread-sicher, wenn sein Zustand und damit die Zustände aller Subsysteme bei parallelen Aufrufen auf definierte Weise ändert.
Dies kann nur dann erreicht werden,

wenn das Programm nur Komponenten verwendet, die ihrerseits thread-sicher sind.
wenn der Zugriff und die Veränderung gemeinsam verwendeter Zustände aus geregelte Weise erfolgt.


P.S.
Übrigens gibt es eine Komponente System.SysUtils.TMultiReadExclusiveWriteSynchroniz er
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
755 Beiträge
 
#22

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 3. Jul 2014, 13:55
Dann wäre doch sinnvoll, z.B. 8 lesende Zugriffe mit
"CriticalSection.EnterRead" gleichzeitig zuzulassen und nur wenn dann ein "CriticalSection.EnterWrite" dazwischen kommen sollte die 8 Leseaktionen zu beenden, den Zugriff wirklich zu sperren und erst danach wieder andere Zugriffe zuzulassen.

Ist meine Überlegung sinnvoll? Oder gar schon so realisiert (in der Hilfe habe ich dazu nichts Genaues gefunden).
Multi-read-Exclusive-write-Synchronizer
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#23

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 3. Jul 2014, 13:58
@Mikkey&Olli73

Danke, genau das meinte ich.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#24

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 3. Jul 2014, 19:19
Bei den aktuellen XEON-MultiCore-Boards hat übrigens jede CPU ihren eigenen Speicher.
[*]The memory slots associated with a given processor are unavailable if the corresponding processor socket is not populated.[*]A processor may be installed without populating the associated memory slots provided a second processor is installed with associated memory. In this case, the memory is shared by the processors. However, the platform suffers performance degradation and latency due to the remote memory.
Das ist aber nicht so richtig das was wir wollen. Scheinbar ist diese Architektur den immer weiter verbreiteten virtuellen (Cloud) Lösungen vorbehalten.
Es ging ja darum, gemeinsamenm Speicher gleichzeitig bearbeiten zu können.
Dass jeder Thread seinen eigenen Speicher bekommt, wäre mit jeder Architektur mit unterschiedlichen Variablen nicht sonderlich schwer zu lösen...
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#25

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 3. Jul 2014, 20:00
Bei den aktuellen XEON-MultiCore-Boards hat übrigens jede CPU ihren eigenen Speicher.
[*]The memory slots associated with a given processor are unavailable if the corresponding processor socket is not populated.[*]A processor may be installed without populating the associated memory slots provided a second processor is installed with associated memory. In this case, the memory is shared by the processors. However, the platform suffers performance degradation and latency due to the remote memory.
Das ist aber nicht so richtig das was wir wollen. Scheinbar ist diese Architektur den immer weiter verbreiteten virtuellen (Cloud) Lösungen vorbehalten.
Es ging ja darum, gemeinsamenm Speicher gleichzeitig bearbeiten zu können.
Dass jeder Thread seinen eigenen Speicher bekommt, wäre mit jeder Architektur mit unterschiedlichen Variablen nicht sonderlich schwer zu lösen...
Die Situation bleibt aber doch gleich, oder weißt du auf welchem Core und welchem Riegel der Wert nun zu finden ist? Und wenn ich der Speicherstelle x einen Wert übergebe, dann muss jeder Thread von dieser Speicherstelle genau den geschriebenen Wert auslesen können.

Das war ja auch nur wegen MultiCore und alle teilen sich einen Arbeitsspeicher
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#26

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 4. Jul 2014, 00:09

Nutzt mir hier ein ThreadPool?

Benötige ich meinen Thread immer wieder, füttere ich „Ihn“ also nur mit neuen Daten und setze einen Event? Oder erzeuge ich den Thread jedes mal neu?
ich bin von den klassischen Anwendungen wie ThreadPools oder Ableitungen von der Klasse TThread ganz weg.
Bei mir gibt es eine Klasse "TThreadExecuter" .. die bekommt einfach einen MethodenPointer und ruft zyklisch wie ein Timer einen MethodenPointer der gewünschten Klasseauf. Meist 1 ms mit Sleep(1) .. aber oft ist das gar nicht notwendig.

So wird eine Funktion, die sich meistens ähnlich schimpft wie "CyclicMainJobs/ CyclicThreadProc" in einem anderen Thread aufgerufen.
Bei Bedarf kann der Aufruf auch schnell alternativ von einem "TTimerExecuter" durchgeführt werden, so wird anstatt eines zweiten Threads die Methode einfach von Hauptthread aus mit einem Timer aufgerufen.

Das Ganze hat den Vorteil, dass man auf alle Variablen der Klasse ohne Umstände Zugriffe hat.
Und das Ganze auch mehr zur "asynchronen" Eventverarbeitung tendiert und mit modernen OOP Konzepten gemeinsam harmoniert, als so eine popelige Schleife lediglich in der abgeleiteten Execute Procedure-

Mit einer übergebenen Instanz einer "SyncKlasse" können auch "teil-global" mehrere Objecte miteinander synchronisiert werden.

Das nur mal als "Brainstorming Idee"....

Aufpassen muss man natürlich, und genau drauf achten, welche Methoden von einem anderem als dem Hauptthread aufgerufen werden ..(werden können).. um dann sauber und ohne Fehler entsprechende Abschnitte im Code zu locken..
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.

Geändert von stoxx ( 4. Jul 2014 um 00:11 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#27

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 4. Jul 2014, 07:56
Meist 1 ms mit Sleep(1) ..
An sich eine coole Idee, aber eine blöde Frage: Ist da nicht ein wenig zu viel context switching und overhead im spiel? Ok, 1000x pro Sekunde irgendwas aufrufen, um zu schauen, ob es etwas zu tun gibt, macht den Kohl nun auch nicht fett, aber ich dachte man ist vom Polling weggekommen. Oder habe ich das falsch verstanden?

Und welche Klasse meinst Du mit 'der gewünschten Klasse'? Und ist der 'Methodenpointer' in der 'gewünschten Klasse' nicht ein Verstoß gegen SRP? Schließlich macht die Methode etwas, das eher mit dem Thread bzw. einer Aktion im Thread zu zun hat, als mit der Klasse an sich.

Wie verhält es sich mit dem OCP, wenn Du eine weitere Aktion im Thread ausführen willst? Dann musst Du ja die gewünschte Klasse aufbohren, d.h. erweitern, obwohl Du an der Funktion der Klasse an sich nichts änderst?

Ich finde einen Workerthread(pool) mit Jobs, die man definiert, implementiert und den Arbeitern zur Verarbeitung gibt, immer noch am elegantesten. Man hat einen Pool pro Anwendung und schmeisst da die Jobs rein, fertig... ne, wie sagt der Fachmann und schon ist der Drops gelutscht.
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
 
Delphi 10.3 Rio
 
#28

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 4. Jul 2014, 10:22

Bei mir gibt es eine Klasse "TThreadExecuter" .. die bekommt einfach einen MethodenPointer und ruft zyklisch wie ein Timer einen MethodenPointer der gewünschten Klasseauf. Meist 1 ms mit Sleep(1) .. aber oft ist das gar nicht notwendig.
Autsch...

Ich würde die Klasse nicht ThreadExecuter, sondern lieber "TSaugdenAkkuleer" oder "TCPUCycleKiller" nennen...

Dafür gibt es doch Waitfor oder Multisyncwait damit der Thread schläft so lange er nicht gebraucht wird.

Mavarik

PS.: Ich habe mir hierfür eine mini Unit gemacht die so was erledigt.

Delphi-Quellcode:
unit UseMyThread;

interface

Uses System.Classes,System.SysUtils,System.SyncObjs,System.Generics.Collections;

type
  TMyThread = class(TThread)
   Private
      FRunning : boolean;
      E_Event : TEvent;
   Protected
      Procedure Execute;override;
   Public
      Constructor Create;
      Destructor Destroy;override;
      procedure Terminate; reintroduce; virtual;
      Procedure MyExecute;Virtual;Abstract;
      Procedure MyFree;Virtual;Abstract;
      Procedure Go;
  end;

  // ProcessorCount


implementation

{ TMyThread }

constructor TMyThread.Create;
begin
  inherited Create(true);

  E_Event := TEvent.Create(NIL,false,false,'');
  FRunning := false;

  FreeOnTerminate := false;
end;

destructor TMyThread.Destroy;
begin
  Terminate;

  inherited;

  try
    MyFree;
  except
  end;

  try
    E_Event.Free;
  except
  end;
end;

procedure TMyThread.Execute;
begin
  while not(Terminated) do
    begin
      try
        FRunning := false; // Atom ?

        E_Event.WaitFor(INFINITE);

        if Terminated then
          exit;

        FRunning := true;
        MyExecute;
      except
      end;
    end;
end;

procedure TMyThread.Go;
begin
  if not(Started) then
    Start;

  E_Event.SetEvent;
end;

procedure TMyThread.Terminate;
begin
  inherited Terminate;
  E_Event.SetEvent;
end;


end.

Geändert von Mavarik ( 4. Jul 2014 um 10:30 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#29

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 4. Jul 2014, 10:56
Ich würde die Klasse nicht ThreadExecuter, sondern lieber "TSaugdenAkkuleer" oder "TCPUCycleKiller" nennen...
Nicht jeder Entwickelt für akkubetriebene Küchenschneidbretter.

Eine Frage zu deinem Code: Hast Du schon mal was von Fail Fast gehört, oder einfach ausgedrückt: "Ordentliches Exception Handling"? Dein "An die Wand gefahren? Merkt doch keiner" ist eventuell schwierig beim Finden von Fehlern.

Noch eine Frage: Wo ist der Mehrwert der Methode 'Go' ggü 'Resume'? Klar, der Aufruf von 'Suspend' ist ein No-Go, aber ansonsten?
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#30

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“

  Alt 4. Jul 2014, 10:57
@Frank

Den Thread im Suspended-Mode zu starten macht irgendwie keinen Sinn, da der doch schon durch den Event wartet.

Ich würde auch nicht TThread.Terminate überschreiben, sondern Tthread.TerminatedSet , denn das ist schon als virtual deklariert und somit zum Überschreiben gedacht.

Die Klasse selber würde ich noch als abstract deklarieren (nur wegen der Dokumentation), denn ohne Ableitung ist die ja so nicht lauffähig.

Einfach so die Exception wegfangen ist auch nicht gerade schön, und wenn fangen, dann nur so:
Delphi-Quellcode:
try
  MyExecute;
except
  // Nur spezielle Exceptions fangen, die MyExecute bewusst ausgelöst hat
  // Alle anderen unvorhergesehenen werden durchgereicht
  on E:MyExecuteException do
    begin
    end;
end;
Das hier
Delphi-Quellcode:
try
  E_Event.Free;
except
end;
ist auch unsauber. Wenn meine Klasse nicht funktioniert, dann möchte ich die Fehler um die Ohren geschlagen bekommen.

Bei dem MyExecute und MyFree sieht das etwas anders aus, da hierfür nicht die Klasse TMyThread zuständig ist.

Aber was passiert denn, wenn in MyExecute ein übler Fehler passiert (StackOverflow)?
Der Code kann immer wieder ausgeführt werden, ohne jeden Hinweis auf den Fehler.

Das Terminate im Destructor ist überflüssig (wird schon implizit vom inherited aufgerufen ... ach nee, bei dir ja nicht )
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 5     123 45      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:28 Uhr.
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