Autor Beitrag
Erichgue
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 86

Win XP/2000/7
TurboPacal 7.0; Delphi 2/5/7; BDS 2006/2010/XE6; C#; MSSQl 2000
BeitragVerfasst: Do 22.03.12 09:31 
Hallo Zusammen!

Folgende Frage beschäftigt mich?
Die Funktion "MachWas" sollte eigendlich Threadsicher sein.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Function TTest.MachWas(Value : Integer) : Integer;
begin
  // 1
  EnterCriticalSection(fLock); 
  // 2
  Result := Value + Value;      
  // 3
  LeaveCriticalSection(fLock);
end;


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
Procedure TThread1.Execute;
begin
  While not Terminated do
  begin
    fTest.Machwas(10);
  end
end


ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
Procedure TThread2.Execute;
begin
  While not Terminated do
  begin
    fTest.Machwas(20);
  end
end


Beide Threads werde gestartet.
Thread1 ruft "Machwas" mit dem Wert 10 auf und steht vor //2
Thread2 ruft "MachWas" mit dem Wert 20 auf und wird durch "EnterCriticalSection" in Machwas erstmal daran gehindert weiter zu machen.
Thread1 wird jetzt weiter ausgeführt. Welchen Wert hat jetzt Value?
Da Thread2 ja bereits in die Function reinkam und seinen Wert in Value übergeben hat.
Rechnet jetzt "MachWas" mit dem Wert 10 von thread1 oder mit dem Wert 20 von thread2?

Vielen Dank!

Erich


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Do 22.03.2012 um 21:45
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Do 22.03.12 09:38 
Das ist ja eine Simple Funtion wie Sin(), ABS() etc. hier gibt es keinerlei Variablen die durch Locking gesichert werden müssten.
Eine halbwegs aktuelle Diskussion zu diesem Thema lief unter www.delphipraxis.net...synchronisieren.html

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
Erichgue Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 86

Win XP/2000/7
TurboPacal 7.0; Delphi 2/5/7; BDS 2006/2010/XE6; C#; MSSQl 2000
BeitragVerfasst: Do 22.03.12 09:44 
Hallo bummi,
es geht je nicht um das was die Funktion macht, sonder um das Prinzip.
Der Link von dir brachte mir schon etwas mehr klarheit.
Um sicher zu gehen, das die Funktion nicht den Übergabeparameter von Thread 2 verwendet,
sollte man die Werte nach EnterCriticalSection zwischen speichern.

Danke!
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Do 22.03.12 10:10 
Die Werte sind auf dem persönlichen Stck des Threads, warum und wohin willst Du etwas zwischenspeichern.
Du könntest ja keine einzige Funktion/Prozedur aus einem Thread heraus aufrufen, wenn es so kompliziert wäre wie Du vermutest.
Die Lockings benötigst Du nur wenn verschiedene Threads auf dieselben Variablen zugreifen müssen.

_________________
Das Problem liegt üblicherweise zwischen den Ohren H₂♂
DRY DRY KISS
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19339
Erhaltene Danke: 1752

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 22.03.12 10:24 
Also:
Du hast eine Klasse, in der steht wie diese aussehen soll. Dann wird ein konkreter Thread erstellt, eine Instanz der Klasse, mit der dann gearbeitet wird.

Jetzt stell dir das ganze am besten so vor:
Ein Architekt hat einen Bauplan (=Klasse) für ein Einfamilienhaus. Nun werden davon zwei gebaut (=Instanzen erstellt). Wenn nun jemand in einem der Häuser etwas aus dem Kühlschrank nimmt, verschwindet es nicht auch in dem anderen. :zwinker:

Solange du also nicht gemeinsame Variablen hast und veränderst (z.B. die selbe Straße vor zwei benachbarten Häusern aufgerissen werden soll), muss also auch keine Synchronisation passieren (in Form von Absperrungen auf der Straße z.B.).
Erichgue Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 86

Win XP/2000/7
TurboPacal 7.0; Delphi 2/5/7; BDS 2006/2010/XE6; C#; MSSQl 2000
BeitragVerfasst: Do 22.03.12 11:19 
Vielen Dank für eure Beiträge!
Ein Test hat bei mir genau das ergeben, was ihr gschrieben habt.
Jetzt kann ich wieder ruhig schlafen.

Danke!

Erich
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: Do 22.03.12 20:58 
Hmm.. Mit mehreren Instanzen einer Klasse hat das eigentlich nichts zu tun. Es geht eher darum, dass bei der Übergabe des Arguments jeweils eine lokale Kopie gemacht wird (man spricht auch von "by value").

Diese Kopie wird bei jedem Aufruf gemacht. Wenn jetzt die Methode auf zwei Threads gleichzeitig ausgeführt wird, dann arbeiten die mit zwei verschiedenen Kopien, die sich nicht beeinflussen. Auch wenn du innerhalb deiner Funktion die Funktion nochmals rekursiv aufrufen würdest, wären das jeweils immer separate Kopien.

Das heisst: Der Parameter "Value" kann auf Thread 1 den Wert 10 haben und auf Thread 2 gleichzeitig den Wert 20 und (bei Rekursionen) auch auf dem Thread 2 den Wert 30 haben. Es ist nicht so, dass "Value" immer nur einen Wert aufs Mal haben kann. Da ist wohl das Missverständnis.

Wie bummi bereits gesagt hat, sind lokale Variablen und Argumente standardmässig auf dem Stack (es gibt Ausnahmen z.B. Closures) oder in einem Register und jeder Thread hat seinen eigenen Stack (und Register). Es ist von einem Thread aus nicht einfach möglich, Werte im Stack eines anderen Threads zu lesen (es sei denn du arbeitest mit Pointern oder machst sonstigen Schwachsinn).

Bei globalen Variablen und Objektdaten sieht das anders aus. Diese sind in einem anderen Bereich des Speichers und "gehören" keinem speziellen Thread oder Aufruf (letzteres auf dem Heap und ersteres sonst irgendwo). Da muss man jeweils aufpassen, dass nicht zwei Threads gleichzeitig unkontrolliert darauf zugreifen.

Deine CritialSections kannst du also weglassen, denn da kommen nur lokale Variablen und Parameter vor, deren Werte bei jedem Aufruf (auch bei Rekursionen im gleichen Thread) auf frische Speicherbereiche gelegt werden.
Erichgue Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 86

Win XP/2000/7
TurboPacal 7.0; Delphi 2/5/7; BDS 2006/2010/XE6; C#; MSSQl 2000
BeitragVerfasst: Fr 30.03.12 16:33 
Danke.
Diese Erklärung hat mir noch gefehlt!