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.
#include<thread> #include<mutex>
und Äquivalente steigern?P.S. Ich benutze GCC, so dass Header vorhanden sind.
Es gibt verschiedene Unterschiede zwischen Boost.Thread und der C++ 11-Standardthreadbibliothek:
std::async
, Boost jedoch nichtboost::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 =).boost::unique_future
Vs std::future
)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.join()
oder detach()
nicht explizit aufrufen, rufen der Destruktor und der Zuweisungsoperator boost::thread
detach()
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.
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.
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.
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.
Mit Visual Studio 2013 kann std::mutex
scheint sich anders zu verhalten als der boost::mutex
, was mir einige Probleme bereitete (siehe diese Frage ).
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.
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.
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.
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.