Pthread Bibliothek - Einen bestimmten Thread aus cond_wait aufwecken



  • Hallo Zusammen,

    vielleicht ist es ja gar nicht so ein komplexes Problem, aber ich mache nun schon etwas länger damit rum und habe keine Lösung gefunden.

    Ich habe mehrere Threads (alle vom gleichen Typ) und führen mit unterschiedlichen Daten genau die gleiche Funktion aus, die bedingt durch eine Condition per pthread_cond_wait() warten müssen.

    T1 T2 T3 T4 T5
    w w w w w w = warten auf die gleiche Bedingung

    Sofern nun ein Zeitpunkt kommt (Ereigniss A) sollen alle wieder weiterlaufen. Dies ist kein Problem, indem ich per pthread_cond_broadcast() alle "schlafenden" Threads wecke und diese ihre Arbeit erledigen. Da die Funktionen die diese aufrufen, lange brauchen, habe ich mehrere Synchronisationspunkte eingebaut, bei denen die jeweiligen Threads die Condition abfragen und gegebenfalls sich schlafen legen müssen.

    Das Problem ist nun, dass ich genau einen Thread davon weiterlaufen lassen will wenn Ereignis B eintritt. Sofern ich nun alle wecken würde mittels pthread_cond_broadcast() und nur angenommen T4 weiterlaufen lassen will, wie könnte ich das anstellen. Also alle anderen Threads sollen weiter schlafen bleiben. Sofern Ereignis A zu einem späteren Zeitpunkt eintritt sollen alle wieder weiterlaufen.

    T1 T2 T3 T4 T5
    w w w w w w = warten auf die gleiche Bedingung
    w w w w w
    w w w w w
    w w w w w
    w w w w w Ereignis B
    w w w a w a = Thread 4 läuft weiter ab, aber alle anderen sollen weiter schlafen
    w w w a w
    w w w a w
    w w w a w
    w w w a w
    w w w - w - = Thread 4 ist fertig geworden
    w w w - w
    w w w - w
    w w w - w
    w w w - w
    w w w - w
    w w w - w Ereignis A
    a a a - a
    a a a - a
    a a a - a
    a a a - a
    - - - - - - = alle anderen Threads sind nun fertig geworden.

    Ich hatte mir gedacht, dass ich das über mehrere Condition-Variablen machen muss, man kann aber ja nur auf eine immer nur warten, d.h. eine Verschachtelung von pthread_cond_wait() bringt nicht, wenn auf Condition X (äußere) gewartet wird, aber Condition Y (innere) signalisiert wird.

    Hättet ihr eine Idee. Ich möchte wie gesagt unterscheiden, dass genau 1 Thread weiterlaufen darf zu, dass alle weiter laufen dürfen.

    Sofern ich nun per pthread_cond_broadcast() signalisierte, dass alle weiterlaufen dürfen, müsste ich auf irgendeine variable hin überprüfen. Jedoch bleibt deren wert auch dann ja bestehen, wenn alle weiter laufen sollen.

    Das Problem ist, dass es nicht immer der gleiche Thread sein wird, der weiterlaufen soll, sondern mal der eine, mal der andere. Ich möchte das nutzen, um einen blockierten (genau einen) zu beenden eigentlich und während er auf die Condition wartet, kann ich ihn ja nicht beenden. Mit Beenden meine ich nicht wirklich killen, weil meine Threads in einer Endlosschleife auf Arbeiten (Jobs) von einer Jobqueue (warteschlange) warten und immer Auftrage absolvieren. Zu einem gegebenen Zeitpunkt soll nun genau ein gewisser Thread (bzw. der eine gewisse Aufgabe erledigt) beenden, also die Aufgabe abbrechen. Der Thread soll wieder auf neue Jobs warten bzw. ist dannach schlafend, sofern nicht alle weiterlaufen dürfen.

    Alle Anderen Threads sollen in der gleichen Zeit aber nicht weiterlaufen, erst wenn ihnen das signalisiert wird.

    thx



  • pthread_cond_signal



  • Sofern ich nun alle wecken würde mittels pthread_cond_broadcast() und nur angenommen T4 weiterlaufen lassen will, wie könnte ich das anstellen.

    Du kannst nur alle oder einen aufwecken. Du kannst nicht explizit sagen welcher das ist. Um dieses Problem zu loesen, gibt es mehrere Moeglichkeiten:

    1.) Du kannst du mittels Variable welcher Thread sich nicht wieder schlafen legen soll. D.h. gewuenschte Thread-Id in Variable ablegen, alle Threads wecken, Threads vergleichen gewuenschte Thread-Id mit ihrer eigenen und legen sich gegebenfalls wieder schlafen.

    2.) Einfach fuer jeden Thread eine eigene condition variable benutzen.

    Sofern ich nun per pthread_cond_broadcast() signalisierte, dass alle weiterlaufen dürfen, müsste ich auf irgendeine variable hin überprüfen. Jedoch bleibt deren wert auch dann ja bestehen, wenn alle weiter laufen sollen.

    Na dann such dir eine Wert aus, der repraesentiert, dass alle weiterlaufen sollen. Bei mehreren condition variable signalisierts du halt allen in einer Schleife.



  • Danke für die Antworten,

    Wenn ich nun aber hingehe und

    Du kannst nur alle oder einen aufwecken. Du kannst nicht explizit sagen welcher das ist. Um dieses Problem zu loesen, gibt es mehrere Moeglichkeiten:

    Genau das ist mein Problem.

    Aber ich möchte ja einen gewissen Auftrag quasi beenden, während ein Thread blockiert ist. Da ich ja nicht weis, welcher Thread diesen Auftrag bearbeitet ist dies schwierig. Oder meinst du, dass ich, wenn der Thread den Auftrag aus der Warteschlange nimmt, eine interne Variable (vom Auftrag) auf die gerade bearbeitende Thread-ID setzte. Möchte ich nun einen Auftrag beenden, setzte ich die Condition auf die Thread-ID (weil ich diese ja nun vom Auftrag kennen) und alle vergleichen auf die Thread-ID, der jenige der den Auftrag bearbeitet beendet sich (hört den Auftrag auf) und wartet auf neue Aufträge. Alle anderen legen sich wieder schlafen. Falls ich nun alle wecken will, setzte ich die Condition auf irgendeinen Wert. Alle vergleichen erstmal ob es dieser Wert ist und sehen dann dass sie weiterlaufen dürfen?

    thx



  • Ergänzung:

    Also sowas in der Art:

    pthread_mutex_lock(lock);
    while (condition) {
    pthread_cond_wait(cond, lock);
    if (job->thread_id == thread_id) break;
    }
    pthread_mutex_unlock(lock);
    

    d.h alle Threads werden geweckt mittels broadcast() (alle schlafen vorher) und schauen nach, ob sie derjenige Thread sind (thread_id wird bei "Abbruch" (besser gesagt einfach Wegnehmen des Auftrags) auf die thread ID des Auftrags gesetzt). Genau 1 Thread (also der die Aufgabe bearbeitet) darf wegen der threads id weiterlaufen, indem er aus der while schleife spring (condition wäre ja noch nicht erfüllt. Alle anderen Threads überprüfen auf condition und legen sich wieder schlafen. Der Thread kann dann Cleanup machen und auf den nächsten Auftrag warten. Sofern nun die condition erfüllt wird und per broadcast() alle geweckt werden, dürfen alle weiterlaufen. Habe ich da einen Denkfehler drinn oder müsste das so funktionieren?

    thx



  • Probiere es aus!


Anmelden zum Antworten