Ich arbeite gerade an einem Problem, das ein erweitertes Producer-Worker-Modell simuliert. In diesem Problem gibt es 3 Arbeiter und 3 Werkzeuge, und damit die Arbeiter arbeiten können, brauchen sie 2 Werkzeuge (und Materialien, aber diese sind irrelevant). Wenn es & lt; 2 Werkzeuge in dem Tresor gibt, wird ein Arbeiter 2 nehmen. Andernfalls werden sie auf eine Bedingungsvariable warten, die signalisiert wird, wenn & gt; = 2 sind.
Das ist in Ordnung mit zwei Arbeitern: Einer wird arbeiten und dann die Werkzeuge zum Tresor zurückbringen, und der andere wartende Arbeiter wird aufwachen und zwei Werkzeuge nehmen. Das Problem ist, dass mit 3 Arbeitern immer einer hungern wird, um die Werkzeuge zu bekommen.
Nach einigen Tests habe ich bemerkt, dass Threads, die auf eine Zustandsvariable warten, in Stack-Form strukturiert sind. Ist es irgendwie möglich, es in die Warteschlange zu stellen? (1 wartet, 2 wartet und 3 wartet. Wenn 1 erwacht ist und einen anderen machen will, muss er hinter 2 und 3 warten.)
Hier ist eine Beispielausgabe. Der Code ist zu lang, also poste ich ihn, wenn es wirklich notwendig ist. Es gibt 3 Worker Threads und 1 Tool Mutex. Wer hungert, unterscheidet sich von jedem anderen Lauf.
%Vor%(Wie Sie sehen können, bekommt 2 die Werkzeuge nie ...)
Aktualisierung: 2013/07/05 Ich habe etwas Code hinzugefügt.
%Vor%Prozessor:
%Vor%makeProducts:
%Vor%getTools:
%Vor%Danke an diejenigen, die geantwortet haben. Ich werde versuchen, heute Nacht eine Warteschlange mit mehreren Bedingungsvariablen zu implementieren.
(P.S. Gibt es eine bessere Möglichkeit, Code-Formatierung hier auf Stack Overflow zu machen? Anders als die vier Leerzeichen ...
std::condition_variable
gibt nicht an, welcher wartende Thread beim Aufruf von notify_one
aktiviert wird. Sie sollten daher Code schreiben, der nicht interessiert, welcher Thread geweckt wird. Das Standardmuster ist dasjenige, welches Thread geweckt wird, dieser Thread sollte die Arbeit erledigen, die erledigt werden muss.
Wenn Sie möchten, dass die Threads in einer bestimmten Reihenfolge aktiviert werden, verwenden Sie einen anderen Mechanismus. Sie könnten beispielsweise für jeden Thread ein eigenes std::condition_variable
haben und dann die Threads in eine Warteschlange stellen, wenn sie Tools benötigen. Wenn ein Thread die Werkzeuge übergibt, könnte er dann die Zustandsvariable entsprechend dem Thread an der Vorderseite der Warteschlange signalisieren. Dieser Thread wird dann geweckt und die anderen werden schlafen (modulo-wecken).
Wenn mehrere Threads auf eine Bedingung warten, die Reihenfolge
in dem sie geweckt werden ( notify_all
) oder was man ist
erwacht ( notify_one
) ist nicht spezifiziert. Wenn Sie irgendeine Art brauchen
Um zu bestellen, müssen Sie notify_all
verwenden und implementieren
dich selber. Sie können eine Warteschlange der Threads warten: vorher
Warten Sie (aber nachdem Sie den Mutex erhalten haben), drücken Sie die Thread-ID auf
das Ende der Warteschlange. In der Schleife, Schleife auf "dieser Thread bei
Vor der Warteschlange und notwendigen Tools zur Verfügung. "Wenn Sie die
Werkzeuge, entfernen Sie die ID von der Vorderseite der Warteschlange und rufen Sie an
notify_all
erneut.
Das eigentliche Problem hier ist, dass wenn Sie Worker-Threads und eine begrenzte Menge an benötigten Ressourcen haben, es Ihnen egal sein sollte, welche Threads tatsächlich aktiviert sind, sollten Sie nur darauf achten, dass die Arbeit erledigt wird. Der einzige Unterschied ist hier in der Protokollierung. Die Anzahl der Threads, die Sie definiert haben, ist die Anzahl der Threads, die parallel ausgeführt werden können und die durch die Ressourcen auf eins beschränkt sind.
Wenn dies für Sie nicht in Ordnung ist, müssen Sie selbst Maßnahmen ergreifen, wie in anderen Antworten erläutert.
Tags und Links c++ multithreading c++11 mutex condition-variable