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 1 von 5  1 23     Letzte »    
Benutzerbild von Mavarik
Mavarik

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

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

  Alt 2. Jul 2014, 02:55
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 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 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 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 ist eine Sammlung für alle interessierten zu zentralisieren. Die Aufgestellten Fragen sind nicht meine (naja vielleicht ein/zwei davon schon)

Geändert von Mavarik ( 2. Jul 2014 um 10:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.016 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#2

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

  Alt 2. Jul 2014, 08:02
Bei dem Titel fiel mir direkt dieser Artikel ein:
What is this thing you call "thread safe"?
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von Sherlock
Sherlock

Registriert seit: 10. Jan 2006
Ort: Offenbach
3.798 Beiträge
 
Delphi 12 Athens
 
#3

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

  Alt 2. Jul 2014, 08:04
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
Oliver
Geändert von Sherlock (Morgen um 16:78 Uhr) Grund: Weil ich es kann
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

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

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

  Alt 2. Jul 2014, 10:22
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...

Bei dem Titel fiel mir direkt dieser Artikel ein:
What is this thing you call "thread safe"?
OK kannte ich nicht...

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

n/a Beiträge
 
#5

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

  Alt 2. Jul 2014, 10:37
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.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

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

  Alt 2. Jul 2014, 11:41
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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#7

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

  Alt 2. Jul 2014, 20:57
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.


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.


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.
  Mit Zitat antworten Zitat
Benutzerbild von stoxx
stoxx

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

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

  Alt 2. Jul 2014, 22:21
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.


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.


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.


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...


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...
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.

Geändert von stoxx ( 3. Jul 2014 um 00:39 Uhr)
  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
 
#9

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

  Alt 2. Jul 2014, 22:40
@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
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
 
#10

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

  Alt 2. Jul 2014, 23:06
@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)

@
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 ....
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.

Geändert von stoxx ( 3. Jul 2014 um 00:31 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


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 21:32 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