C ++ 11 nicht blockierender Produzent / Verbraucher

8

Ich habe eine C ++ 11-Anwendung mit einem Thread mit hoher Priorität, der Daten produziert, und einem Thread mit niedriger Priorität, der ihn verbraucht (in meinem Fall auf Festplatte schreiben). Ich möchte sicherstellen, dass der Produzententhread mit hoher Priorität niemals blockiert wird, d. H. Er verwendet nur Lock-Free-Algorithmen.

Mit einer blockierungsfreien Warteschlange kann ich Daten aus dem Producer-Thread in die Warteschlange pushen und sie aus dem Consumer-Thread abfragen, wodurch meine oben genannten Ziele erreicht werden. Ich möchte mein Programm so ändern, dass der Consumer-Thread blockiert, wenn er inaktiv ist und nicht abfragt.

Es scheint, als ob die C ++ 11-Zustandsvariable nützlich sein könnte, um den Consumer-Thread zu blockieren. Kann jemand mir ein Beispiel zeigen, wie man es benutzt, während man die Möglichkeit vermeidet, dass der Verbraucher mit Daten schläft, die sich noch in der Warteschlange befinden? Genauer gesagt, möchte ich sicherstellen, dass der Verbraucher immer einige Zeit aufgeweckt wird, nachdem der Produzent den letzten Gegenstand in die Warteschlange geschoben hat. Es ist auch wichtig, dass der Produzent nicht blockierend bleibt.

    
nonagon 28.01.2014, 19:27
quelle

3 Antworten

1
  

Es scheint, als ob die C ++ 11-Zustandsvariable nützlich sein könnte, um den Consumer-Thread zu blockieren. Kann jemand mir ein Beispiel zeigen, wie man es benutzt, während man die Möglichkeit vermeidet, dass der Verbraucher mit Daten schläft, die sich noch in der Warteschlange befinden?

Um eine Zustandsvariable zu verwenden, benötigen Sie einen Mutex und eine Bedingung. In Ihrem Fall lautet die Bedingung "Es sind Daten in der Warteschlange verfügbar". Da der Hersteller sperrfreie Updates verwendet, um Arbeit zu produzieren, muss der Konsument die gleiche Form der Synchronisation verwenden, um die Arbeit zu konsumieren, so dass der Mutex nicht zur Synchronisierung verwendet wird und nur vom Consumer-Thread benötigt wird, weil es keine gibt andere Möglichkeit, auf eine Zustandsvariable zu warten.

%Vor%

Die Bedingungsvariable blockiert nur im Aufruf wait , wenn die Warteschlange vor dem Warten leer ist. Die Bedingungsvariable kann fälschlicherweise aufwachen oder weil sie vom Hersteller gemeldet wurde. In beiden Fällen wird sie jedoch nur vom Aufruf wait zurückgegeben (statt wieder zu schlafen), wenn die Warteschlange nicht leer ist. Dies wird durch die Verwendung der condition_variable::wait -Überladung gewährleistet, die ein Prädikat übernimmt, weil die Bedingungsvariable das Prädikat immer wieder für Sie überprüft.

Da der Mutex nur vom Consumer-Thread verwendet wird, könnte er tatsächlich lokal für diesen Thread sein (solange Sie nur einen Consumer haben, müssen mehrere den gleichen Mutex verwenden, um auf denselben Condvar zu warten ).

    
Jonathan Wakely 28.01.2014 23:49
quelle
0

Eine Lösung, die ich in der Vergangenheit gefunden habe, war die Verwendung von Windows-Ereignissen ( Ссылка ). In diesem Fall bleibt das Ereignis so lange angezeigt, bis es einen wartenden Thread aufweckt, und wenn keine Threads warten, bleibt es signalisiert. Also muss der Produzent einfach das Ereignis signalisieren, nachdem er Daten in die Warteschlange geschoben hat. Dann sind wir garantiert, dass der Verbraucher eine endliche Zeit danach aufwachen wird.

Ich konnte jedoch keine Möglichkeit finden, dies mithilfe der Standardbibliothek zu implementieren (zumindest nicht ohne den Erzeuger-Thread zu blockieren).

    
nonagon 29.01.2014 19:17
quelle
0

Ich denke, Semaphore könnten verwendet werden, um dieses Problem sicher zu lösen:

%Vor%

Leider glaube ich nicht, dass C ++ 11 einen Semaphor enthält? Ich konnte auch nicht bestätigen, dass das Freigeben eines Semaphors eine nicht blockierende Operation ist. Sicher Implementierungen mit Mutexe z. C ++ 0x hat keine Semaphore? Wie man Threads synchronisiert? erlaubt keinen blockierungsfreien Produzenten-Thread.

    
nonagon 29.01.2014 19:27
quelle