AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Änderungen von Variablen synchronisieren

Ein Thema von Breager · begonnen am 17. Mär 2012 · letzter Beitrag vom 20. Mär 2012
Antwort Antwort
Breager

Registriert seit: 18. Feb 2012
40 Beiträge
 
#1

Änderungen von Variablen synchronisieren

  Alt 17. Mär 2012, 10:58
Hallo,

ich hoffe, der Titel ist treffend. Ich habe eine Variable vom Typ String, die sowohl innerhalb eines Threads als auch außerhalb des Threads verändert werden kann. Die Wahrscheinlichkeit ist wohl sehr gering, aber ich befürchte, dass es theoretisch zu Problemen kommen könnte, wenn ich versuche, den Wert dieser Variablen gleichzeitig innerhalb des Threads und außerhalb des Threads zu ändern.

Hier mein Lösungsversuch:
Delphi-Quellcode:
Var ThreadString:AnsiString;
    TreadString_Locked:Boolean;

//Innerhalb des Threads
Begin
...
 ThreadString_Locked:=True;
 ThreadString:='Neuer Wert';
 ThreadString_Locked:=False;
...
End;

//außerhalb des Threads:

Function SetThreadString(s:AnsiString):Boolean;
Var TimeOut:Integer;
Begin
 TimeOut:=0;
 Repeat
 IF not(ThreadString_Locked) then
    BEGIN
     ThreadString:=s;
     Result:=True;
    END ELSE
     Result:=False;

 Inc(TimeOut);
Until TimeOut>1000;
End;
Solange der Wert innerhalb des Threads durch die Variable ThreadString_Locked gesperrt ist, kann der Variablen außerhalb des Threads nichts zugewiesen werden.

Ist dieser Ansatz sinnvoll bzw., gibt es eine einfachere oder besser Lösung?

Gruß

Geändert von Breager (17. Mär 2012 um 11:02 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
 
#2

AW: Änderungen von Variablen synchronisieren

  Alt 17. Mär 2012, 11:11
Jo, z.B. Delphi-Referenz durchsuchenTCriticalSection

und auch mal hier schauen Hier im Forum suchenTCriticalSection
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 Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: Änderungen von Variablen synchronisieren

  Alt 17. Mär 2012, 12:16
Apropos Timeout -> du hast da nen Vergleich mit 1000 gemacht, was evt. impliziert, dass du wirklich 1000 ms (1 sek) warten möchtest. Das ist aber nicht der Fall.. Das sind einfach 1000 Schleifendurchläufe; daher ist das auch abhängig von der Prozessorgeschwindigkeit. Verarbeitet dein Prozessor einen Schleifendurchgang in genau einer ms, dann würde das stimmen, nur ist das nicht der Fall. Diese Schleife ist binnen kürzester Zeit durchlaufen (<10ms?)

...nur ne Kleinigkeit ^^
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.326 Beiträge
 
Delphi 12 Athens
 
#4

AW: Änderungen von Variablen synchronisieren

  Alt 17. Mär 2012, 13:47
Booleans sind nicht threadsicher, vorallem da sie nichtmal atomar änderbar sind, da die CPU mir kompletten Registern arbeitet und dann nur die Bytes raus ANDed und SCHIFTet.
Die CPUs kennen da einen speziellen Befehl LOCK

z.B. LOCK MOV [EAX], EDX statt MOV [EAX], EDX .
Und die WinAPI kennt die Interlocked-Behle, wie MSDN-Library durchsuchenInterlockedExchange.


Deine "innere" Änderung von ThreadString ist nicht abgesichert, denn da wird nicht geprüft, ob der String gerade von SetThreadString verändert wird.

Gut, man könnte jetzt beide Zeiten absichern und dann äußere und inner Änderungen nur über dieses SetThreadString ausführen,
Delphi-Quellcode:
Function SetThreadString(s:AnsiString):Boolean;
Var TimeOut:Integer;
Begin
 TimeOut:=0;
 Repeat
   IF not(ThreadString_Locked) then
    BEGIN
     ThreadString_Locked:=True;
     ThreadString:=s;
     ThreadString_Locked:=False;
     Result:=True;
    END ELSE
     Result:=False;

 Inc(TimeOut);
Until TimeOut>1000;
End;
aber hier kann es immernoch vorkommen, daß mehrere Threads gleichzeitig durch das IF kommen und :=True setzen, da diese Beiden erst Recht nicht atomar sind.

Ich hatte letzens die CriticalSection über TryEnter und eine Schleife mit einem TimeOut versehn.
Schön ist das nicht unbedingt, aber es funktioniert wenigstens.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Breager

Registriert seit: 18. Feb 2012
40 Beiträge
 
#5

AW: Änderungen von Variablen synchronisieren

  Alt 17. Mär 2012, 18:50
Vielen Dank für Eure Antworten!

Mir brummt schon ganz schön der Schädel. Vielleicht warte ich doch lieber, bis der Thread beendet wurde

Brauche ich zum Lesen auch eine CriticalSection? Wird der Code innerhalb der CriticalSection in eine Warteschleife gelegt und später abgearbeitet oder einfach nicht ausgeführt/ignoriert? Letzteres wäre vorallem beim Lesen ungünstig.

Zitat von himitsu:
Ich hatte letzens die CriticalSection über TryEnter und eine Schleife mit einem TimeOut versehn.
Danke. Im Grunde also das, was ich mit meinem Code erreichen möchte (ein Pollen sozusagen).

Bin gerade über TMultiReadExclusiveWriteSynchronizer gestolpert, was haltet ihr davon? Ich muss den Wert vorwiegend lesen.
  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
 
#6

AW: Änderungen von Variablen synchronisieren

  Alt 17. Mär 2012, 21:01
Eigentlich ist das mit der TCriticalSection sehr einfach.

Stell dir eine Kreuzung vor. Die beiden Straßen sind einmal der MainThread und der Thread den du laufen lässt. Die CriticalSection ist nun die Ampel, die dafür sorgt, dass über den Kreuzungspunkt (Zugriff auf die Variable) immer nur eine Fahrbahn (Thread) freigegeben ist.

Delphi-Quellcode:
TMyThread = class( TThread )
strict private
  FCS : TCriticalSection;
private
  FIntStr : string;
  procedure SetIntStr( const Value : string );
  function GetIntStr : string;
protected
  procedure Execute; override;
public
  property IntStr : string read GetIntStr write SetIntStr;
end;

...

procedure SetIntStr( const Value : string );
begin
  FCS.Enter; // Betreten der CS
  try
    FIntStr := Value;
  finally
    FCS.Leave; // Verlassen der CS
  end;
end;

function GetIntStr : string;
begin
  FCS.Enter; // Betreten der CS
  try
    Result := FIntStr;
  finally
    FCS.Leave; // Verlassen der CS
  end;
end;
Bei FCS.Enter wird solange gewartet, bis die CriticalSection frei ist und dann betreten.
Innerhalb eines Thread-Kontexts darf die CS sooft betreten werden, wie man möchte. Die CS sperrt ja nur gegen Zugriffe durch unterschiedliche Thread-Kontexte.

Die Getter und Setter der Eigenschaft kümmern sich nun darum, dass der Zugriff geregelt wird, egal aus welchem Thread-Kontext man darauf zugreift.
Aber ... innerhalb des Threads könnte man ja direkt auf FIntStr zugreifen, aber dieser Zugriff ist nicht abgesicht (über die CS), also sollte der Zugriff auch innerhalb des Threads über die Eigenschaft und nicht über das Feld erfolgen.
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
  while not Terminated do
  begin
    ...
    // FIntStr := 'So nicht';
    IntStr := 'So geht das';
    ...
  end;
end;
end;
Der Vollständigkeit halber sei noch erwähnt, dass die Instanz von FCS natürlich von TMyThread im Constructor erzeugt und im Destructor wieder freigegeben werden sollte bzw. muss.
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)

Geändert von Sir Rufo (17. Mär 2012 um 21:05 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 07:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz