Announcement

Collapse
No announcement yet.

Thread und Schreib-/Lesezugriffe

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Thread und Schreib-/Lesezugriffe

    Hallo,<br>ich habe eine Verständnisfrage zum Thema Threads. Mir ist bekannt, das ich Schreibzugriffe synchronisieren muß (z.B. TCriticalSection). Jetzt habe ich eine kleine Testanwendung, die mehrere Threads abspaltet. Diese Threads lesen Eigenschaften des Hauptformulars. Muß ich diese Lesezugriffe synchronisieren ? Weiterhin senden die Thread mit SendMessage und PostMessage ein paar Botschaften zum Hauptformular.
    Einige dieser Botschaften lösen ein Add in einer TListbox aus.
    Werden die Messages von Windows synchronisiert, oder muß ich das selber machen ? Irgendwo habe ich mal gelesen, dass Windows angeblich Botschaften synchronisiert.<br>:-) Jens Schumann

  • #2
    Hallo,

    unter Win32 wird jeder Thread preemtiv vom Windows-Scheduler unterbrochen, damit sein Nachbar Rechenzeit auf dem Prozessor bekommt. Somit muss man bei jedem Lesezugriff, der mehrere CPU-Takte benötigt, mit Ärger rechnen, wenn dieser Zugriff nicht geschützt wird. Bei einer Eigenschaft (die über Set- und Get-Methoden implementiert wird) ist das immer der Fall. Außerdem ist der Zugriff auf das im primären Thread ausgeführte Hauptformular der Anwendung bis auf wenige Ausnahmen extra zu schützen - nicht umsonst hat TThread die Methode <b>Synchronize</b> im Angebot.

    Nur die mit <b>PostMessage</b> abgeschickten Botschaften werden in die Botschaftswarteschlange abgelegt und somit automatisch von Windows synchronisiert. Im Gegensatz sorgt ein Aufruf von <b>SendMessage</b> dafür, dass sofort die Fensterprozedur aufgerufen wird (was bei mehreren Threads zu Problemen führen kann)

    Comment


    • #3
      Ich habe nun eine ähnliche Frage:

      Eigentlich benutze ich in meinem Thread nur im Thread erzeugte Objekte und Variablen. Es sollte keine Aufrufe über die Threadgrenze hinaus gehen. Allerdings bekomme ich trotzdem Probleme. Der erste Thread arbeitet scheinbar innerhalb normaler Parameter, aber der zweite stürzt bei ganz simplen Sachen ab.
      Zur Anmerkung sei gesagt, dass der Threadcode ansich nur folgendermaßen aussieht:
      <pre>
      procedure TMyThread.Execute;
      begin
      DoSomething;
      end;
      <br>
      procedure TMyThread.DoSomething;
      begin
      while not Terminated do begin
      Optimierung.NextStep;
      end;
      end;
      <br>
      constructor TMyThread.create(OrderPool: TOrderPool);
      begin
      Optimierung:=TOptimierung.Create(Application,Order Pool);
      FreeOnTerminate := True;
      inherited Create(False);
      end;

      </prE>
      Die Fehler passieren immer innerhalb des TOptimierung-Codes, an unterschiedlichen Stellen.

      Woran kann es liegen

      Comment


      • #4
        Hallo,

        &gt;Woran kann es liegen?

        bei allen verwendeten Funktionen (Delphi oder Win32) muss man in der Dokumentation nachlesen, ob diese eine Thread-Abhängigkeit besitzen. Nicht alle VCL-Teile sind Threadfest

        Comment


        • #5
          Z.b. Der Threadcode nutzt ObjectTextToBinary(). Im ersten Moment erscheint die trivial sicher, aber intern wird um einige Ecken herum auf globale Objecte und Listen zugegriffen. Damit wäre dies nicht mehr threadsafe.<br>

          Es hängt nun von der Implementierung Deiner Optimierungsklasse ab.<br>
          Dein obiger Code ist soweit threadsicher.<br>

          Übrigens, alles was im TThread.Create() erzeugt wird ist dem Thread zugeordnet der diesen Thread erzeugt hat. D.h. TThread.Create() läuft im Context des erzeugenden Threades.<br> NUR die .Execute; Methode ist der eigentliche Thread. D.h. will man sicherstellen das ein alloziertes Object auch wirklich im TThread Context erzeugt wird so müsste man es in .Execute erzeugen.<br>
          ABER, im Grunde spielt das keine Rolle wer was erzeugt, da alle Resourcen immer einem Prozess zugeordnet sind. Wichtiger ist die Frage WER greift WANN und WIE auf Daten zu.
          Grundsätzlich gibt es keinerlei Unterscheidungen ob dies Schreibend oder Lesend geschiet, bei beidem treten Threadsynchronisierungs Probleme auf. Denn da wo einer Schreibt könnte ein anderer Lesen, und da wo einer oder mehrere Lesen kann es einen geben der schreibt.<br>
          D.h. grundsätzlich sollte beim threadübergreifenden Zugriff auf gemeinsamme Daten ALLE Threads den Lese- und Schreibzugriff synchronisieren.<br> Also auch der MainThread MUSS dann synchronisiert werden.
          Am besten macht man eine Procedure/Function insich threadsafe indem sie per RTL-CriticalSections blockt. Dies wäre die sichere Alternative aber im Grunde inpraktikabel, da nicht 1000'ende Proceduren eigene RTL-CS's benutzen können und da dadurch der Deadlock provoziert wird.<br>
          Zudem wird die Gesamtperformance stark reduziert das die Wahrscheinlichkeit steigt das sie mehrer Threads in solchen threadsafe Proceduren gegeseitigt lange Zeit sperren.<br>

          .Synchronize() sollte Threadsafe arbeiten da sie bestimmte Eigenschaften des OS und dessen Messagehandlings ausnutzt. ABER, der Teufel steckt im Detail, da ab D6 genau hier der Code an Kylix angepasst werden musste. Nunmehr sind Threads unter Windows und Kylix ein Problem.<br>
          .Synchronize ist aber ein relativ langsammer Weg um threadsicher zu arbeiten. Des öfteren ist es deshalb, z.B. bei Statusmeldungen, besser per PostMessage() zu arbeiten. Das verbleibende Problem beschränkt sich darauf das mit dieser Methode eventuelle Datenpackete auf die gemeinsam zugegriffen wird, denoch per RTL-CS abgesichert werden müssen.<br>
          Unter Windows ist im Grunde nur der Weg über Events und dem Signalisieren "das der Weg frei ist" der optimale.

          Gruß Hage

          Comment

          Working...
          X