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)