Ich frage mich, ob dies der richtige Ansatz zum Schreiben einer thread-sicheren Warteschlange in C ++ ist?
%Vor%Sie haben die Idee ... Ich frage mich nur, ob das der beste Ansatz ist. Danke!
BEARBEITEN: Wegen der Fragen, die ich bekomme, wollte ich klarstellen, dass der Mutex ein boost :: mutex
istHerb Sutter schrieb letztes Jahr einen ausgezeichneten Artikel ausgezeichneten Artikel im Dr. Dobbs Journal die Hauptanliegen für eine thread-sichere, lock-freie Single-Producer-Single-Consumer-Queue-Implementierung. (Die Korrekturen über eine Implementierung der letzten Monat veröffentlicht.)
Sein Follow-up-Artikel in der nächsten Ausgabe behandelte einen allgemeineren Ansatz für eine Warteschlange für mehrere Benutzer gleichzeitig vollständige Diskussion über mögliche Fallstricke und Leistungsprobleme.
Es gibt noch ein paar Artikel zu ähnlichen Nebenläufigkeitsthemen.
Viel Spaß.
Ich empfehle, die Boost-Threading-Bibliotheken zu verwenden, um Sie dabei zu unterstützen.
Ihr Code ist in Ordnung, außer dass wenn Sie Code in C ++ wie
schreiben %Vor% Wenn der Code im Abschnitt // do something
eine Ausnahme auslöst, wird die Sperre niemals aufgehoben. Die Boost-Bibliothek löst dies mit ihren Klassen wie lock_guard , in dem Sie ein Objekt initialisieren, das im Konstruktor eine Sperre erhält und dessen Destruktor die Sperre aufhebt. Auf diese Weise wissen Sie, dass Ihr Schloss immer freigegeben wird. Andere Sprachen erreichen dies durch try / finally-Anweisungen, aber C ++ unterstützt dieses Konstrukt nicht.
Was passiert insbesondere, wenn Sie versuchen, aus einer Warteschlange ohne Elemente zu lesen? Ist das eine Ausnahme? Wenn ja, dann würde Ihr Code auf Probleme stoßen.
Wenn Sie versuchen, das erste Element zu bekommen, möchten Sie wahrscheinlich prüfen, ob etwas da ist, und dann schlafen gehen, wenn nicht und warten, bis etwas ist. Dies ist ein Job für ein Bedingung -Objekt , auch von der Boost-Bibliothek bereitgestellt, wenn auch auf einer niedrigeren Ebene verfügbar.
Von einem Threading-Point aus gesehen, der für eine einfache Thread-sichere Warteschlange richtig aussieht.
Sie haben jedoch ein Problem: Das pop () -Parameter von std :: queue gibt das aus der Warteschlange herausgefallene Element nicht zurück. Was Sie tun müssen, ist:
%Vor%Sie möchten in diesem Fall keine Referenz zurückgeben, da das referenzierte Element aus der Warteschlange entfernt und zerstört wird.
Sie müssen auch eine öffentliche size () -Funktion haben, um Ihnen zu sagen, wie viele Elemente sich in der Warteschlange befinden (oder dass Sie den Fall bearbeiten müssen, in dem Pop () aufgerufen wird und in dem sich keine Elemente befinden die Warteschlange).
Bearbeiten: Obwohl Eli Courtwright darauf hinweist, müssen Sie vorsichtig sein, wenn die Warteschlangenoperationen Ausnahmen auslösen, und die Verwendung von Boost ist eine gute Idee.
Der Ansatz, den Sie zu implementieren versuchen, ist ein Locking-Ansatz. Es funktioniert, außer, dass wenn Sie ein einfaches "Mutex" -Objekt verwenden, dessen Leistung sich als enttäuschend erweist (sein Lock-Unlock-Overhead ist ziemlich hoch). Es ist schwer zu sagen, ob es gut ist oder nicht, da wir nicht wissen, was Ihre Leistungsanforderungen und Erwartungen sind.
Da die Operationen, die Sie in "gesperrten" Segmenten Ihres Codes ausführen, ziemlich schnell sind, kann es sinnvoll sein, anstelle eines echten Mutex oder einer Kombination aus beiden eine Drehsperre zu verwenden. Dadurch erhalten Sie eine viel bessere Leistung. Vielleicht implementiert dein "Mutex" das alles schon (keine Möglichkeit zu wissen, da du keine Details darüber angegeben hast, was sich hinter diesem Namen versteckt).
Und schließlich, wenn Sie zufällig nach der besten Leistung suchen, möchten Sie vielleicht den lockfreien Synchronisierungsansatz lesen, der eine völlig andere Geschichte ist. Lock-Free-Methoden sind jedoch in der Regel viel schwieriger zu implementieren.
Wie Jean-Lou Dupont darauf hingewiesen hat, ist Ihr aktueller Code ziemlich anfällig für Deadlocks. Als ich das getan habe, habe ich drei Sperren verwendet: zwei gezählte Semaphore und einen Mutex. Die gezählten Semaphoren signalisieren wenn:
Tags und Links c++ multithreading thread-safety concurrency