webentwicklung-frage-antwort-db.com.de

Ist es klug, boost :: thread und boost :: mutex durch C ++ 11-Entsprechungen zu ersetzen?

Motivation: Grund für meine Überlegung ist, dass mein genialer Projektmanager meint, Boost sei eine weitere Abhängigkeit, und dass es schrecklich ist, weil "Sie darauf angewiesen sind" (ich habe versucht, die Qualität des Boosts zu erklären, gab dann nach einiger Zeit auf :( Ein kleinerer Grund, warum ich es tun möchte, ist, dass ich C++ 11-Funktionen lernen möchte, weil die Leute anfangen werden, Code darin zu schreiben.

  1. Gibt es eine 1: 1 Zuordnung zwischen #include<thread> #include<mutex>und Äquivalente steigern?
  2. Würden Sie eine gute Idee finden, Boost-Zeug durch C++ 11 zu ersetzen?
    Zeug. Meine Verwendung ist primitiv, aber gibt es Beispiele, bei denen std nicht das bietet, was boost tut? Oder (Gotteslästerung) umgekehrt?

P.S. Ich benutze GCC, so dass Header vorhanden sind.

149
NoSenseEtAl

Es gibt verschiedene Unterschiede zwischen Boost.Thread und der C++ 11-Standardthreadbibliothek:

  • Boost unterstützt die Thread-Löschung, C++ 11-Threads nicht
  • C++ 11 unterstützt std::async, Boost jedoch nicht
  • Boost verfügt über einen boost::shared_mutex Für das Sperren mehrerer Leser/Einzelschreiber. Das analoge std::shared_timed_mutex Ist nur seit C++ 14 ( N3891 ) verfügbar, während std::shared_mutex Nur seit C++ 17 ( N4508 verfügbar ist =).
  • C++ 11-Timeouts unterscheiden sich von Boost-Timeouts (dies sollte sich jedoch bald ändern, da Boost.Chrono akzeptiert wurde).
  • Einige der Namen sind unterschiedlich (z. B. boost::unique_future Vs std::future)
  • Die Argumentübergabe-Semantik von std::thread Unterscheidet sich von boost::thread --- Boost verwendet boost::bind, Wofür kopierbare Argumente erforderlich sind. Mit std::thread Können Nur-Verschieben-Typen wie std::unique_ptr Als Argumente übergeben werden. Aufgrund der Verwendung von boost::bind Kann auch die Semantik von Platzhaltern wie _1 In verschachtelten Bindungsausdrücken unterschiedlich sein.
  • Wenn Sie join() oder detach() nicht explizit aufrufen, rufen der Destruktor und der Zuweisungsoperator boost::threaddetach() für das zu zerstörende Thread-Objekt auf. Zugewiesen an. Bei einem C++ 11-Objekt std::thread Wird dadurch std::terminate() aufgerufen und die Anwendung abgebrochen.

Um den Punkt über Nur-Verschieben-Parameter zu verdeutlichen, ist C++ 11 gültig und überträgt den Besitz des int vom temporären std::unique_ptr Auf den Parameter von f1. wenn der neue Thread gestartet wird. Wenn Sie jedoch boost::thread Verwenden, funktioniert dies nicht, da boost::bind Intern verwendet wird und std::unique_ptr Nicht kopiert werden kann. Es gibt auch einen Fehler in der mit GCC gelieferten C++ 11-Threadbibliothek, der dies verhindert, da std::bind Auch in der dortigen Implementierung verwendet wird.

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

Wenn Sie Boost verwenden, können Sie wahrscheinlich relativ problemlos zu C++ 11-Threads wechseln, wenn Ihr Compiler dies unterstützt (z. B. haben neuere Versionen von GCC unter Linux eine größtenteils vollständige Implementierung der C++ 11-Threadbibliothek, die in -std=c++0x Modus).

Wenn Ihr Compiler C++ 11-Threads nicht unterstützt, können Sie möglicherweise eine Drittanbieterimplementierung wie Just :: Thread abrufen, dies ist jedoch immer noch eine Abhängigkeit.

186

std::thread Ist weitgehend nach boost::thread Modelliert, mit ein paar Unterschieden :

  • die Semantik der nicht kopierbaren Ein-Handle-Zuordnung von Boost zu einem-OS-Thread bleibt erhalten. Dieser Faden ist jedoch beweglich, um das Zurückführen des Fadens von den Werksfunktionen und das Platzieren in Behältern zu ermöglichen.
  • Dieser Vorschlag fügt dem boost::thread Eine Stornierung hinzu, was eine erhebliche Komplikation darstellt. Diese Änderung wirkt sich nicht nur auf den Thread, sondern auch auf den Rest der C++ - Threading-Bibliothek aus. Es wird angenommen, dass diese große Änderung aufgrund des Nutzens gerechtfertigt ist.
    • Der Thread-Destruktor muss vor dem Trennen jetzt cancel aufrufen, um zu verhindern, dass versehentlich untergeordnete Threads verloren gehen, wenn übergeordnete Threads abgebrochen werden.
    • Ein explizites Trennungsmitglied ist jetzt erforderlich, um das Trennen ohne Abbrechen zu ermöglichen.
  • Die Konzepte Thread-Handle und Thread-Identität wurden in zwei Klassen unterteilt (sie sind in boost::thread Dieselbe Klasse). Dies erleichtert die Manipulation und Speicherung der Thread-Identität.
  • Die Möglichkeit, eine Thread-ID zu erstellen, die garantiert mit keinem anderen beitrittsfähigen Thread verglichen werden kann, wurde hinzugefügt (boost::thread Hat dies nicht). Dies ist praktisch für Code, der wissen möchte, ob er vom selben Thread wie ein vorheriger Aufruf ausgeführt wird (rekursive Mutexe sind ein konkretes Beispiel).
  • Es gibt eine "Hintertür", durch die das native Thread-Handle abgerufen werden kann, sodass Clients Threads auf Wunsch mit dem zugrunde liegenden Betriebssystem bearbeiten können.

Dies ist aus dem Jahr 2007, daher sind einige Punkte nicht mehr gültig: boost::thread Hat jetzt eine native_handle - Funktion, und std::thread Ist laut Kommentatoren nicht mehr stornierbar.

Ich konnte keine signifikanten Unterschiede zwischen boost::mutex Und std::mutex Feststellen.

23
Alex B

Enterprise-Fall

Wenn Sie Software für Unternehmen schreiben, die auf einer mäßigen bis großen Vielfalt von Betriebssystemen ausgeführt werden muss und folglich mit einer Vielzahl von Compilern und Compilerversionen (insbesondere relativ alten) auf diesen Betriebssystemen aufbaut, ist es mein Vorschlag, sich von diesen fernzuhalten C++ 11 insgesamt für den Moment. Das bedeutet, dass Sie std::thread Nicht verwenden können, und ich würde empfehlen, boost::thread Zu verwenden.

Basic/Tech Startup Case

Wenn Sie für ein oder zwei Betriebssysteme schreiben, müssen Sie mit Sicherheit immer nur mit einem modernen Compiler arbeiten, der hauptsächlich C++ 11 unterstützt (z. B. VS2015, GCC 5.3, Xcode 7), und Sie sind es noch nicht Abhängig von der Boost-Bibliothek könnte std::thread eine gute Option sein.

Meine Erfahrung

Ich persönlich stehe auf gehärtete, stark genutzte, sehr kompatible, sehr konsistente Bibliotheken wie Boost im Vergleich zu einer sehr modernen Alternative. Dies gilt insbesondere für komplizierte Programmieraufgaben wie das Threading. Außerdem habe ich mit boost::thread (Und Boost im Allgemeinen) in einer Vielzahl von Umgebungen, Compilern, Threading-Modellen usw. große Erfolge erzielt. Wenn es meine Wahl ist, wähle ich Boost.

6
Nicholas Smith

Es gibt einen Grund, nicht nach std::thread Zu migrieren.

Wenn Sie statische Verknüpfungen verwenden, wird std::thread Aufgrund der folgenden GCC-Fehler/-Funktionen unbrauchbar:

Wenn Sie nämlich std::thread::detach Oder std::thread::join Aufrufen, führt dies entweder zu einer Ausnahme oder zu einem Absturz, während boost::thread In diesen Fällen ordnungsgemäß funktioniert.

6
ks1322

Mit Visual Studio 2013 kann std::mutex scheint sich anders zu verhalten als der boost::mutex, was mir einige Probleme bereitete (siehe diese Frage ).

3
Robert Hegner

In Bezug auf std :: shared_mutex in C++ 17 hinzugefügt

Die anderen Antworten geben einen sehr guten Überblick über die Unterschiede im Allgemeinen. Es gibt jedoch mehrere Probleme mit std::shared_mutex, Die das Problem lösen.

  1. Erweiterbare Mutices. Diese fehlen in std::thread. Sie ermöglichen es einem Leser, zu einem Schreiber aufgewertet zu werden, ohne dass andere Schreiber vor Ihnen einsteigen können . Mit diesen Funktionen können Sie beispielsweise im Lesemodus eine große Berechnung vorverarbeiten (z. B. eine Datenstruktur neu indizieren) und dann ein Upgrade durchführen, um den Neuindex anzuwenden, während Sie die Schreibsperre nur für kurze Zeit gedrückt halten.

  2. Gerechtigkeit. Wenn Sie eine konstante Leseaktivität mit einem std::shared_mutex Haben, werden Ihre Writer auf unbestimmte Zeit gesperrt. Dies liegt daran, dass ein anderer Leser immer Vorrang hat, wenn er mitkommt. Mit boost:shared_mutex Wird allen Threads irgendwann Priorität eingeräumt.(1) Weder Leser noch Schriftsteller werden ausgehungert.

Dies bedeutet, dass, wenn Sie ein System mit sehr hohem Durchsatz ohne Ausfallzeiten und mit sehr hoher Konkurrenz haben, std::shared_mutex Niemals für Sie funktionieren wird, ohne ein Prioritätssystem manuell darauf aufzubauen. boost::shared_mutex Funktioniert sofort, obwohl Sie in bestimmten Fällen daran basteln müssen. Ich würde argumentieren, dass das Verhalten von std::shared_mutex Ein latenter Fehler ist, der darauf wartet, in den meisten Code, der ihn verwendet, vorzukommen.

(1)Der tatsächlich verwendete Algorithmus basiert auf dem OS-Thread-Scheduler. Nach meiner Erfahrung gibt es bei gesättigten Lesevorgängen unter Windows längere Pausen (beim Erhalt einer Schreibsperre) als unter OSX/Linux.

1
Robert Fraser

Ich habe versucht, shared_ptr von std anstelle von boost zu verwenden und tatsächlich einen Fehler in der gcc-Implementierung dieser Klasse gefunden. Meine Anwendung stürzte ab, weil der Destruktor zweimal aufgerufen wurde (diese Klasse sollte threadsicher sein und keine derartigen Probleme verursachen). Nach dem Umzug nach boost :: shared_ptr sind alle Probleme verschwunden. Aktuelle Implementierungen von C++ 11 sind noch nicht ausgereift.

Boost hat auch mehr Funktionen. Beispielsweise stellt der Header in der Standardversion keinen Serialisierer für einen Stream bereit (d. H. Cout << duration). Boost verfügt über viele Bibliotheken, die ihre eigenen Entsprechungen usw. verwenden, jedoch nicht mit Standardversionen zusammenarbeiten.

Fazit: Wenn Sie bereits eine Anwendung mit boost geschrieben haben, ist es sicherer, den Code beizubehalten, als sich um die Umstellung auf den C++ 11-Standard zu bemühen.

0
user3323559