Autor Beitrag
Bergmann89
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Mo 14.03.11 18:36 
Hey,

ich steh mal wieder vor einem Problem bei der Thread-Synchronisierung, wo ich nicht recht weiter weiß. Meine Threads bekommen einen Satz Daten und den Listen-Index dieser Daten. Die Daten müssen jetzt der Reihe nach durch 5 verschiedene Routinen. Die Routinen wissen den Index des Datensatzes der als nächstes bearbeitet werden soll. Die Daten sollen aufsteigen von 0 bis n-1 verarbeitet werden. Jetzt müssen die Threads aber auch bestimmte Regeln befolgen:
1. Betritt keine Routine, die bereits von einem anderen Thread ausgeführt wird (kein Problem da nehm ich CriticalSections, Mutex oder Semaphor)
2. Betritt keine Routine, wenn der Index deiner Daten größer als der aktuell zu bearbeitende Index ist (und hier weiß ich nicht ganz weiter)
Die einzige Idee, die ich hab ist folgende: Ich mach ne Schleife über alle Routinen. Routinen, die bereits erfolgreich ausgeführt wurden werden übersprungen. Die Schleife wird erst beendet, wenn der Thread alle Routinen abgearbeitet hat. Mit der Methode verschenk ich aber Rechenleistung und das gefällt mir nicht wirklich. Ich such jetzt irgendwie nach ner Möglichkeit den Thread zu pausieren, bis seine Daten an der Reihe sind berechnet zu werden. Hat da jmd ne Idee?

€: die Threads kennen sich untereinander nicht, also kann ich da auch meine Events oder sowas benutzten bzw. mit fällt jetzt nicht ein wie ich die sinnvoll nutzen könnte...

MfG & Thx Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19326
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 14.03.11 20:11 
user profile iconBergmann89 hat folgendes geschrieben Zum zitierten Posting springen:
Ich such jetzt irgendwie nach ner Möglichkeit den Thread zu pausieren, bis seine Daten an der Reihe sind berechnet zu werden. Hat da jmd ne Idee?
Erzeuge mit CreateEvent ein Event und warte darauf mit WaitForMultipleObjects. ;-)
Dann kannst du das Event mit SetEvent auslösen. Das funktioniert auch mit Threads.
Bergmann89 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Mo 14.03.11 21:08 
Hey,

mit dem Gedanken habe ich ja auch schon gespielt, aber da kommt ich auch nich weiter. Bsp:
Thread 1 mit ID = 0
Thread 2 mit ID = 1
Thread 3 mit ID = 2
die Routine erwaret Daten mit ID = 0
Thread 2 will in die Routine, hat nicht die richtige ID, also wartet er auf sein Event.
Thread 3 will in die Routine, hat nicht die richtige ID, also wartet er auch auf sein Event.
Thread 1 will in die Routine, hat die richtige ID, arbeitet alles ab... Un nun? Wenn jeder Thread das Event selbst besitzt und als Methode oder Eigenschaft zur verfügung stellt, dann weiß Thread 1 nicht welchen Thread er ansprechen soll, weil sich die Threads untereinander nicht kennen. Wenn ich die Events in der Routine speicher, dann müsste ich so ne Art Liste machen, oder ein Array mit je einem Event pro Thread. Aber das halte ich auch irgendwie für komisch :?
Vlt sollte ich die Aufgaben der Threads anderes verteilen und jedem Thread eine Kopie der Liste geben die er dann in einer Routine abarbeitet. Anstatt wie jetzt jeder Thread jede Routine mit einem Datensatz. Da müsste ich auch weniger synchronisieren.

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^
Bergmann89 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1742
Erhaltene Danke: 72

Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
BeitragVerfasst: Di 15.03.11 21:25 
Hey,

hab meine Denkblockade überwinden können, aber so ganz will es noch nicht funktionieren. Und zwar kommt es ab und zu zum Deadlock. Hier der Code (vereinfacht):
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
Finished := False;
repeat
  WaitResult := WaitForSingleObject(fSemaphor, SEMAPHORE_WAIT_TIME);
  try
    case WaitResult of
      WAIT_OBJECT_0: begin
        if Thread.DataID > fNextID then begin 
          Finished := False
        end else begin  
          {rechne was}
          Finished := True;
        end;
      end;
    else
      Finished := True;
      {Errorhandling...}
    end;
  finally
    if not ReleaseSemaphore(fSemaphor, 1nilthen begin
      Finished := True;
      {Errorhandling...}
    end;  
  end;
  if not Finished then begin
    ResetEvent(fWaitEvent);
    if WaitForSingleObject(fWaitEvent, INFINITE) <> WAIT_OBJECT_0 then begin
      Finished := True;
      {Errorhandling...}
    end;  
  end;
until Finished;
SetEvent(fWaitEvent);

Ein Thread kommt in den Arbeitsbereich, und schützt als erstes den Zugriff auf den Bereich mit einem Semaphor. Dann guckt er ob er die benötigte DatenID hat. Wenn ja dann darf er weiter rechnen. Dann verlässt er den geschützen Bereich (gibt den Semaphor frei). Wenn er nicht die richtige ID hat, dann wartet er auf ein Event. Das wird jetzt solange wiederholt, bis die Routine soweit hinterher ist, dass die Daten des Threads an der Reihe sind. Sobald ein Thread die Routine verlässt ruft er das Event auf, um die wartenden Threads zu wecken, das diese erneut prüfen können, ob sie rechnen dürfen oder sich wieder schlafen legen sollen.
Ich find aber den Fehler nicht. Sieht jmd von euch, wo da der Deadlock enstehen kann?!

MfG Bergmann.

_________________
Ich weiß nicht viel, lern aber dafür umso schneller^^