Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Lokale Variable Threadsicher? (https://www.delphipraxis.net/175098-lokale-variable-threadsicher.html)

saihttam 30. Mai 2013 08:56

Delphi-Version: 2007

Lokale Variable Threadsicher?
 
Moin zusammen,
bei uns ist eine heiße Diskussion über Threadsicherheit entbrannt... hoffentlich gibt es hier eine klare Antwort.

Folgendes:
1..n Threads benutzen ein einmal erzeugtes Objekt.
Die Threads rufen eine Funktion namens Cmd parallel auf.
Code:
function TMyObject.Cmd(tx: String; var rx: String): Boolean;
var
  myClient: TMyClient;
begin
  //myClient erzeugen
  //myClient benutzen
  //FreeAndNil...
end;
Jetzt gibt es zwei Theorien.

1. Die 'myClient' wird bei parallelen Aufrufen an den gleichen Pointer erzeugt. Und damit ist diese Konstrukt NICHT thread-sicher!

2. 'myClient' wird an verschiedenen Pointern erzeugt und solange man keine globale Variablen benuzt, ist es thread-sicher.
2a. Wenn den so ist warum funktioniert dann Rekursion.

Danke+Gruß
Matthias

Uwe Raabe 30. Mai 2013 09:07

AW: Lokale Variable Threadsicher?
 
Die lokalen Variablen und die Parameter einer Methode werden auf dem Stack angelegt oder es wird ein Register der CPU benutzt. Das ist in jedem Fall threadsicher. Bei Pointern, dynamischen Arrays und Klasseninstanzen (sind ja auch Pointer) muss man aber wiederum aufpassen. Die Inhalte liegen nämlich nicht auf dem Stack.

In dem konkreten Beispiel wird aber die Klasseninstanz innerhalb der Methode erzeugt und freigegeben. Das ist wiederum sicher.

Rekursion hat damit erstmal gar nichts zu tun. Auch hier muss man eine konkrete Implementation sehen, um Threadsicherheit beurteilen zu können. Es gelten da die gleichen Bedingungen.

jaenicke 30. Mai 2013 09:59

AW: Lokale Variable Threadsicher?
 
Zitat:

Zitat von saihttam (Beitrag 1216948)
2. 'myClient' wird an verschiedenen Pointern erzeugt und solange man keine globale Variablen benuzt, ist es thread-sicher.

Wobei du zu den globalen Variablen auch die Felder des Objekts zählen musst, zu dem deine Funktion Cmd gehört, also was dort unter private, public usw. steht.

Zitat:

Zitat von saihttam (Beitrag 1216948)
2a. Wenn den so ist warum funktioniert dann Rekursion.

Weil du dort die Parameter für den einzelnen Aufruf als Parameter übergibst. Du benutzt dort ja nicht die selbe lokale Variable über mehrere Rekursionsschritte hinweg.

Beispiel:
Delphi-Quellcode:
function Test(const a: Integer): Integer;
begin
  if a > 1 then
    Result := Test(a - 1)
  else
    Result := 1;
end;
Wenn du dort z.B. 3 übergibst, wird innerhalb deines Aufrufs Test(3) noch einmal Test(2) und Test(1) aufgerufen. Ob du darin dann jeweils noch einmal lokale Variablen benutzt oder nicht, ist egal. Denn die gelten jeweils nur innerhalb des aktuellen Aufrufs. Das sich in der Rekursion ändernde Element ist a, also der Parameter. Und der wird auch nur dem jeweiligen Aufruf mitgegeben.

Wir könnten hier sicherlich auch erklären wie das intern genauer funktioniert, aber ich glaube das führt zu weit und verwirrt eher. (Auch wenn es sehr interessant sein kann. ;-))

Der schöne Günther 30. Mai 2013 11:07

AW: Lokale Variable Threadsicher?
 
Falls Ihr euch regelmäßig zum Philosophieren über den Begriff Threadsicherheit trefft - Ich fand den kleinen Artikel ganz nett: Eric Lippert - What is this thing you call thread-safe?

Sir Rufo 30. Mai 2013 11:55

AW: Lokale Variable Threadsicher?
 
Zitat:

Zitat von saihttam (Beitrag 1216948)
1. Die 'myClient' wird bei parallelen Aufrufen an den gleichen Pointer erzeugt. Und damit ist diese Konstrukt NICHT thread-sicher!

Das ist generell schon mal absolut falsch - und wäre auch absolut tödlich

Delphi-Quellcode:
function MyFactory : TObject;
var
  LObj : TObject;
begin
  LObj := TObject.Create;
  Result := LObj;
end;
Wenn das so wäre, dann würde man sich ja bei jedem Aufruf die vorherige damit erzeugte Instanz vernageln.
Kann also definitv nicht zutreffen.

saihttam 31. Mai 2013 09:32

AW: Lokale Variable Threadsicher?
 
Zwar ist immer noch nicht klar warum es an dieser Stelle 'knallt' aber, dass muss dann wohl einen anderen Grund haben als das Multi-Threading.

Vielen Dank für die Antworten!
Grüße Matthias

Sir Rufo 31. Mai 2013 09:50

AW: Lokale Variable Threadsicher?
 
Zitat:

Zitat von saihttam (Beitrag 1217068)
Zwar ist immer noch nicht klar warum es an dieser Stelle 'knallt' aber, dass muss dann wohl einen anderen Grund haben als das Multi-Threading.

Vielen Dank für die Antworten!
Grüße Matthias

Es liegt nicht an den lokalen Variablen ;)

Update:

Bzw. es kann schon daran liegen, allerdings ist die Ursache eine falsche Handhabung.
Eine lokale Variable ist beim Aufruf nicht initialisiert. Soll heißen, die zeigt auf irgendeine Stelle im Speicher.
Greift man nun auf diese Variable einfach so zu, dann können die lustigsten Sachen passieren.

z.B. das hier
Delphi-Quellcode:
procedure TForm1.Foo;
var
  LForm : TForm;
begin
  LForm.Close;
end;
kann zu einer Exception oder auch dazu führen, dass eine x- beliebige Form geschlossen wird ;)
Darum schmeisst der Compiler auch eine Warnung aus, wenn eine lokale Variable nicht initialisiert wurde.

Das solltest du zuerst prüfen (Compiler-Warnungen, Initialisierung der lokalen Variablen)
Danach, ob irgendwelche Abhängigkeiten von aussen (z.B. bei einer lokal erzeugten Query eine "globale" Connection benutzen) eingeschleust werden.

Der schöne Günther 31. Mai 2013 10:02

AW: Lokale Variable Threadsicher?
 
Was tritt denn auf?

Vom Namen hier sieht das aus wie eine Methode zum Absetzen einer Zeichenfolge an ein Gerät und man bekommt darauf eine Antwort. Wenn wir hier jetzt bsp. eine Leitung haben, auf der man tunlichst die erste Nachricht zuende schreibt und die Antwort empängt bevor man mit der zweiten weitermacht, wären kritische Abschnitte (zumindest für den Hardware-Teil auf der physikalischen Leitung) genau das richtige...

sahimba 31. Mai 2013 11:01

AW: Lokale Variable Threadsicher?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1216951)
In dem konkreten Beispiel wird aber die Klasseninstanz innerhalb der Methode erzeugt und freigegeben. Das ist wiederum sicher.

Das lässt sich so nicht sagen, da wir nicht wissen, was die Instanz der erzeugten Klasse intern "tut". Möglicherweise greift diese auf globale Strukturen zu ohne sich um eine Synchronisierung zu kümmern.

saihttam 31. Mai 2013 11:42

AW: Lokale Variable Threadsicher?
 
@Sir Rufo
Ich habe mir abgewöhnt Compilerwarungen zu ignorieren, das rächt sich irgendwann...:)

Es geht darum, dass ein weiterer Service via TCP angesprochen wird. Am Empfängerservice ist zu sehen, dass die Anfragen nahezu zur gleichen Zeit (<=1ms) ankommen und den gleichen Port benutzen.
Deswegen war ich auf die lokalen Variablen gestoßen.

Das Ganze konnte ich zum Testen mit einer TCriticalSection lösen, also muss das Problem ja innerhalb dieser Funtkion liegen. Sind Firmensourcen daher kann ich den Code leider nicht einstellen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:38 Uhr.
Seite 1 von 2  1 2      

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