Delphi-PRAXiS
Seite 1 von 5  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“ (https://www.delphipraxis.net/180940-die-frage-aller-fragen-sammlung-%84ist-das-thread-safe-%93.html)

Mavarik 2. Jul 2014 01:55


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

Ich glaube Jeremy North hat mal geschrieben: „Wenn ich für jede Frage: „Ist das Thread-Safe“, einen Dollar bekommen würde, bräuchte ich nicht mehr zu arbeiten“ (frei übersetzt)…

Ich möchte hier mal diesen Diskussion-Thread :lol: starten um die häufigsten Frage und Antworten zu sammeln.

Was bedeutet eigentlich Thread-Safe?

Oder müsste die eigentliche Frage lautet: „Ist xy reentrant?“

Also was darf ich in einen Thread machen und was nicht und wann brauche ich ein Syncronize?

Wenn man(n) nach Thread safe googled oder auch DP’ed bekommt man schon unzählige Antworten. Jedoch beantworten 99 von 100 Suchergebnissen nicht den „eigentlichen“ Kern der Frage, oder?

Was ist den Atomar?
Wann brauche ich ein critical section?
Wann brauche ich eine Semaphore?
Oder reicht mir ein Spinlock?

Sicherlich gibt es hierzu Tutorials. Zum Beispiel hier!

Besonders bemerkenswert ist hieraus folgenden Satz:

Zitat:

Zitat von Lossy eX
Und wenn man alles synchronisiert, dann kann man auch komplett auf den Thread verzichten. Weil dadurch alles im VCL-Thread ausgeführt wird. Und das ist ja eigentlich nicht Sinn und Zweck davon

Ich kenne „nur“ die Aussage die VCL ist nicht Thread safe! FMX „wahrscheinlich“ auch nicht.
Das lassen wir einfach mal so stehen. Aber ist die VCL/FMX reentrant?

Reden wir hierbei von den Komponenten oder über die Systemroutinen?
Was gehört zu dieser VCL Aussage?

Was ist mit einem lesenden Zugriff in einem Thread nach dem Motto:

Delphi-Quellcode:
procedure TMyThread.Execute;
var
  S : String;
begin
  while not(Terminated) do
  begin
    S := Edit10.Text;
    Foo(S);
  End;
end;
Brauche ich für den Zugriff auf Edit10.Text ein Syncronize?
Was kann passieren?

OK, nochmal zurück zum Grund der Frage.

Warum möchte man überhaupt einen Thread erzeugen?

a.) Eine Verarbeitung soll parallel laufen oder im Hintergrund
b.) Die Software soll schneller werden.
c.) ??

Erst mal zu b.

Zitat:

Zitat von Physikalischer Ausflug
Beim aktuellen Stand der Technik ist die Taktrate der CPU - auf Grund der Lichtgeschwindigkeit und der sich daraus ergebenden Strecken die vom Strom zurückgelegt werden können - beschränkt und es ist ein Ende erreicht/in Sicht..
Wenn nicht alles noch kleiner wird müssen andere Techniken her, denn teilweise ist die Sperrschicht der Transistoren schon nur noch wenige Atome dick.

Ein Programm kann also nur schneller werden, wenn die Arbeit auf verschiedene Prozessor-Kerne ausgelagert wird.

Aber was will ich den beschleunigen?

Bei „normalen“ Programmen (was ist schon normal) wartet die Software zu 99,9% auf die Eingabe des Benutzers. Aber dann… Wenn der Benutzer eine Aktion ausführt soll es doch möglichst schnell gehen.
Es wurde dann immer gesagt: „Mach doch die komplizierte Berechnung in einem Thread!“

Was ist den eine komplizierte Berechnung und woher kommen die Daten? Wir reden ja nicht davon Pi auf 1000 Stellen zu berechnen, sondern eher von 3*7+StrtoInt(Edit10.Text) + 19% MwSt. Summe(SQL-Table)… Aber genau da kommen wir zu „unserem“ Punkt.

Können 2 Thread’s StrtoInt aufrufen? Was ist mit einer SQL-Abfrage? Dateioperationen? Drucker Zugriff?

Ich könnte mir vorstellen, dass eine TTable die auf ein Formular geklickt wurde „schlecht ist um in einem Thread benutzt zu werden, aber was ist wenn ich diese im Thread lokal erzeuge?

Gibt es System Routinen die nicht gleichzeitig von mehreren Thread aus aufgerufen werden dürfen?
Was ist mit den Indy-Routinen? Ich nutze gerne einen Thread für http oder SOAP Requests. Funktioniert prima… Aber das gehört eher zu (a)

Wie lange muss meine Routine eigentlich dauern, damit es sich lohnt diese in einen Thread aus zu lagern?
Das erzeugen des Thread’s mit kompletten overhead kostet ja auch Zeit. Also für die 10 Fälle wo ich einen Thread brauche diesen schon beim Programmstart erzeugen? Kann ich das erzeugen der Threads in einen Thread auslagern? :-)

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?

Wie ist denn meine Aufgabenstellung?

Fragen über Fragen und dann noch die Unsicherheit ob das alles so Safe ist… oder ob ich mir Deadlocks erzeuge…

Kommen wir mal zurück zu Punkt (a)
Schön ist es wenn ich eine Verarbeitung in einen Thread auslagern kann, dieser Thread dann - wenn er fertig ist - eine Procedure aufruft, die dann das Ergebnis verarbeiten kann. (Idealfall)

Was ist aber wenn ich auf das Ergebnis warten muss?

Beispiel:
Ich habe eine http Request und will das den erhaltenen content dann verarbeiten. Solange ich nicht das Ergebnis in meinem Workflow brauche, sondern die Inhalte nur gespeichert werden sollen. Prima, aber was wenn der User damit etwas machen soll?

Ich starte also den Thread für den Request… Mache „schnell“ noch was anderes im Vordergrund task und dann? Muss ich auf das Ergebnis warten, oder ist es schon da? Das hängt natürlich von der Internet und CPU Geschwindigkeit ab. Diese also dann vorher testen und dann entscheiden ob Thread oder nicht?

Ich denke es gibt hier noch genügend Fragen die noch zu beleuchten sind. Auch weil die Thread Implementierung von Delphi zu Delphi Version immer „besser“ geworden ist.

Wie sind Eure Erfahrungen?
Wie häufig nutzt Ihr Threads und wo für?
Soll man eine Library nehmen oder von Fall zu Fall den Thread neu programmieren?
Wie sieht es auf anderen Plattformen aus? Android/iOS/Mac…

Lasst und mal sammeln…

Grüsse Mavarik

PS.: Die Intention dieses Threads 8-) ist eine Sammlung für alle interessierten zu zentralisieren. Die Aufgestellten Fragen sind nicht meine (naja vielleicht ein/zwei davon schon) :stupid:

Stevie 2. Jul 2014 07:02

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Save?“
 
Bei dem Titel fiel mir direkt dieser Artikel ein:
What is this thing you call "thread safe"?

Sherlock 2. Jul 2014 07:04

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Save?“
 
OT:
Und du hast nur die Spitze des Eisbergs gesehen, Google mal nach "thread safe". Da kippste um!

Sherlock
-dem man so früh am Morgen den Rechtschreib-Flame verzeihen möge

Mavarik 2. Jul 2014 09:22

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

Zitat von Sherlock (Beitrag 1264025)
OT:
Und du hast nur die Spitze des Eisbergs gesehen, Google mal nach "thread safe". Da kippste um!

Aber hilft das? Oh ja verstehe...
Aber wenigstens konsequent durchgesetzt...

Zitat:

Zitat von Stevie (Beitrag 1264024)
Bei dem Titel fiel mir direkt dieser Artikel ein:
What is this thing you call "thread safe"?

OK kannte ich nicht...

Dejan Vu 2. Jul 2014 09:37

AW: Die Frage aller Fragen (Sammlung): „Ist das Thread-Safe?“
 
Ich glaube, 'ist das threadsafe' kann man sich anhand der Definition im Wiki selbst beantworten.
Die Frage lautet, wann setzt man Threads sinnvoll ein?

Mir fallen drei Szenarien ein:
  1. Viele Aktionen werden in einer Schleife abgearbeitet. Die GUI soll dabei aus ästhetischen Gründen nicht blockiert werden, die Schleife soll man aber abbrechen können. Das geht hemdsärmelig mit 'Application.ProcessMessages', aber ein Thread ist eleganter (Background Thread).
  2. Einkommende Aufträge sollen abgearbeitet werden. Der Empfang einkommender Aufträge darf nicht blockiert werden. (Workerthread mit Queue, Overlapped Execution).
  3. Viele voneinander unabhängige Aktionen müssen in möglichst kurzer Zeit durchgeführt werden (Parallele Threads)
Natürlich gibt es noch mehr Szenarien, Mischformen und Ausprägungen dieser Grundprobleme.

p80286 2. Jul 2014 10:41

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

Zitat von Stevie (Beitrag 1264024)
Bei dem Titel fiel mir direkt dieser Artikel ein:
What is this thing you call "thread safe"?

Nach der Lektüre kann ich Mavarik gut verstehen.

Gruß
K-H

BUG 2. Jul 2014 19:57

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

Zitat von Mavarik (Beitrag 1264017)
Oder reicht mir ein Spinlock?

Das riecht irgendwie nach Ärger: Synchronisationsmittel nicht selbst implementieren. Das Konzept klingt einfach, aber es gibt einige Tücken. Sperr-Synchronisation ist auf höherer Ebene schwer genug ... da sollte sich der Anwendungsentwickler nicht noch mit den Caches rumschlagen.


Zitat:

Zitat von Mavarik (Beitrag 1264017)
Ich kenne „nur“ die Aussage die VCL ist nicht Thread safe! FMX „wahrscheinlich“ auch nicht.
Das lassen wir einfach mal so stehen. Aber ist die VCL/FMX reentrant?

Die beiden Konzepte sind orthogonal zueinander. Man kann eine reentrante API haben, die nicht tread-safe ist und umgekehrt. Unix-Betriebssystem-Aufrufe sind öfter beides. Allgemeine Bibliotheken sind meist beides nicht.


Zitat:

Zitat von Mavarik (Beitrag 1264017)
Fragen über Fragen und dann noch die Unsicherheit ob das alles so Safe ist… oder ob ich mir Deadlocks erzeuge…

Tja, mit den Deadlock-Freiheit ist das so eine Sache. Wenn man eine Lock-Hierarchy einhält oder zyklische Abhängigkeiten anderweitig vermeidet, mag man das noch beweisen können; ansonsten sieht es im Allgemeinen düster aus.

stoxx 2. Jul 2014 21:21

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

Zitat von Mavarik (Beitrag 1264017)
Hallo Zusammen!
Was ist den Atomar?
Wann brauche ich ein critical section?
Wann brauche ich eine Semaphore?
Oder reicht mir ein Spinlock?


Eine parallele Verarbeitung ist doch was schönes. Egal wie schnell eine einzige CPU noch werden kann.
Vielleicht existiert ja auch Software, die nicht nur auf simple Usereingaben wartet.


Zitat:

Zitat von Mavarik (Beitrag 1264017)
Hallo Zusammen!
Was ist den Atomar?

Atomar heißt, dass die CPU sicherstellt, dass ein Vorgang wirklich nacheinander, also serialisiert durchgeführt wird.
Wie im Wikipedia Artikel auch beschrieben, zieht das zwangsläufig ebenso nach sich, dass ein Thread oder nenn es auch "Vorgang" in seiner Arbeit für eine bestimmten Moment nicht unterbrochen werden darf (durch einen Interrupt)

Die Threadsicherheit geht je nach verwendeter CPU schon bei einem normalen Integer verloren. 4 Byte.
Zwei Threads arbeiten mit einer Integervariablen. Der eine schreibt gerade die erste Hälfte von den 4 Bytes, der andere Thread liest aber gerade in dem Moment die Integervariable. Du siehst, die Daten sind nicht die, die Du erwartest und schon gar nicht logisch richtig.
Ein Boolean ist wohl wirklich atomar Threadsicher.
Atomar bedeutet einfach, dass die Technick herum um die Software irgendwann nur noch die Threadsicherheit übernehmen kann. In dem Fall die CPU. Critical Sections selbst müssen atomar sein. In dem Fall vom Betriebssystem zur Verfügung gestellt.


Zitat:

Zitat von Mavarik (Beitrag 1264017)
Hallo Zusammen!
Wann brauche ich ein critical section?

immer sobald mehrere Threads mit Daten arbeiten, und einer davon schreibend auf Daten tätig ist.
Schon das Arbeiten mit einer Liste muss abgesichert werden.
If list.Count > 0 .. dann mache irgendwas, kann schon zu Programmabstürzen führen, wenn gerade in dem Moment ein anderer Thread was aus der Liste löschen würde, und bei der Abfrage: list.count noch ein Element drin ist, und dann beim Zugriff auf das Element es auf einmal gar nicht mehr da wäre.


Zitat:

Zitat von Mavarik (Beitrag 1264017)
Hallo Zusammen!
Wann brauche ich eine Semaphore?

Critical Sections funktionieren nicht Prozessübergreifend ... ein Semaphore oder Mutex bräuchtest Du beim gemeinsamen Zugriff zweier Programme auf eine Datei, auf gemeinsame Daten, auf gemeinsame Dinge...


Zitat:

Zitat von Mavarik (Beitrag 1264017)
Hallo Zusammen!
Oder reicht mir ein Spinlock?

Ein Spinlock ist nur ein Zusatzfeature einer Critical Section oder beliebigen Lock Methode.
Das Anhalten eines Threads mit einer Critical Section führt in hochperformanten Anwendungen zu Performance Verlusten.
Ein Spinlock lässt den zu wartenden Thread einfach ein paar Millisekunden im "Kreise" drehen, und wenn dann die Freigabe immer noch noch nicht erteilt ist, erst dann geht er in "Ruhezustand"..
Für all Deine beschriebenen Anwendungen, die nur auf "Usereingaben" warten ist das alles nicht relevant.
*smile*

Für nähere Infos siehe auch Microsofts "InitializeCriticalSectionAndSpinCount" function.

Allerdings sind Spinlocks bei Zugriff auf Daten von mehr als 2 Threads großer Mist und werden in der Praxis meiner Erfahrung nach etwas "hakelig". Manche Threads kommen dann gar nicht gleichranging zum Zug. Da ist die Betriebssysteminterne Verwaltung mit Critical Sections tausend Mal besser. Da gehts geordnet der Reihe nach, die Threads werden vom Betriebssystem in geordneter Reihenfogle aus dem Ruhezustand geholt.

Wenn man all seine Programme versteht, ist alles gar nicht so schwer ..
Ein sauberer modularer Programmierstil ist unerlässlich mit sauberen Schnittstellen nach außen...

Sir Rufo 2. Jul 2014 21:40

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

Wenn ein Integer nach deiner Darstellung nicht sicher ist, dann kann auch ein Boolean unsicher sein (hängt davon ab wie ein Boolean intern gespeichert/verarbeitet wird).

Bei 32bit werden allerdings - soweit mir bekannt - immer genau 4 Bytes (=32bit) bearbeitet, und deswegen ist ein 8/16/24/32bit-Wert auf einem 32bit-Betriebssystem threadsafe, denn die CPU lockt dafür den Speicherplatz (32bit) im Arbeitsspeicher.

Darum ist es ja auch ein 32bit-Betriebssystem, das eine 32bit CPU benötigt.
Darum sind 64bit-Programme teilweise langsamer, weil eben bei jedem Zugriff immer 64bit bewegt (doppelte Menge).
  • Arbeitet die Anwendung bevorzugt mit 32bit-Werten (z.B. Integer), dann wird das unter 64bit langsamer als unter 32bit.
  • Arbeitet die Anwendung bevorzugt mit 64bit-Werten (z.B. Int64, Cardinal), dann wird das unter 64bit schneller als unter 32bit.

Ehrlich gesagt würde ich aber selbst einen Zugriff auf einen Integer mit einem Lock absichern, bzw. eigentlich tausche ich fast immer komplexere Datenelemente mit einem Thread aus, wo alles enthalten ist um die Aufgabe zu erledigen. Mit nur einem Integer-Wert ist das eher selten möglich :)

stoxx 2. Jul 2014 22:06

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

Zitat von Sir Rufo (Beitrag 1264172)
@stoxx

Wenn ein Integer nach deiner Darstellung nicht sicher ist, dann kann auch ein Boolean unsicher sein (hängt davon ab wie ein Boolean intern gespeichert/verarbeitet wird).

>Edit< .. hab meinen vorigen Text nochmal editiert .. genau genommen trifft das in der Tat auch auf booleans zu.
Auch egal, wie er gespeichert, verarbeitet wird, nämlich immer dann, wenn der Wert geprüft wird, und dann vielleicht geändert.
(ist das gleiche Problem, wie unten mit dem increment vom Integer beschrieben)

Zitat:

Zitat von Sir Rufo (Beitrag 1264172)
@
Bei 32bit werden allerdings - soweit mir bekannt - immer genau 4 Bytes (=32bit) bearbeitet, und deswegen ist ein 8/16/24/32bit-Wert auf einem 32bit-Betriebssystem threadsafe, denn die CPU lockt dafür den Speicherplatz (32bit) im Arbeitsspeicher.


das hängt von der CPU ab.
Ein auf dem eigenem Rechner programmiertes und getestes Programm muss noch lange nicht stabil überall funktionieren.
So pauschal kann man das nicht sagen. Es hängt nicht vom Betriebssystem ab, sondern von der CPU (und vom Compiler) ..

Hier mal beispielhaft die Aussagen von Intel

https://software.intel.com/en-us/forums/topic/308940


ich hab auch irgendwo mal eine komplette umfangreiche Liste gefunden, ich werde mal suchen ...

Nicht atomar zu sein heißt ja auch, 2 Threads wollen einen Wert incrementieren.
Beide lesen den Wert 5, und schreiben (leider gleichzeitig) 6 hinein.
Wenn das beide gleichzeitig machen, steht am Ende 6 drin, obwohl 2 Threads zweimal hochgezählt haben und 7 drinstehen müsste.
Daher auch die existierende Windows Funktion InterlockedIncrement ....


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:01 Uhr.
Seite 1 von 5  1 23     Letzte »    

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