Motivation: Grund, warum ich darüber nachdenke, ist, dass mein genialer Projektmanager denkt, dass Boost eine weitere Abhängigkeit ist und dass es schrecklich ist, weil "Sie davon abhängen" (ich habe versucht, die Qualität von Boost zu erklären, und dann nach einiger Zeit aufgegeben :( ) Ein kleinerer Grund, warum ich das tun möchte, ist, dass ich C ++ 11-Funktionen lernen möchte, weil die Leute anfangen, Code darin zu schreiben. Also:
- Gibt es eine 1: 1-Zuordnung zwischen
#include<thread> #include<mutex>
und Boost-Äquivalenten? - Würden Sie eine gute Idee in Betracht ziehen, Boost-Inhalte durch C ++ 11-
Inhalte zu ersetzen? Meine Verwendung ist primitiv, aber gibt es Beispiele, bei denen std nicht bietet, was Boost bewirkt? Oder (Gotteslästerung) umgekehrt?
PS Ich benutze GCC, also sind Header da.
Antworten:
Es gibt verschiedene Unterschiede zwischen Boost.Thread und der C ++ 11-Standard-Thread-Bibliothek:
std::async
, Boost jedoch nichtboost::shared_mutex
Sperre für mehrere Leser / einzelne Schreiber. Das Analogestd::shared_timed_mutex
ist nur seit C ++ 14 ( N3891 )std::shared_mutex
verfügbar , während es nur seit C ++ 17 ( N4508 ) verfügbar ist .boost::unique_future
vsstd::future
)std::thread
unterscheidet sich von der Verwendung vonboost::thread
--- Boostboost::bind
, für die kopierbare Argumente erforderlich sind.std::thread
Ermöglicht die Übergabe von Nur-Verschieben-Typenstd::unique_ptr
als Argumente. Aufgrund der Verwendung vonboost::bind
kann auch die Semantik von Platzhaltern wie_1
in verschachtelten Bindungsausdrücken unterschiedlich sein.join()
oderdetach()
dann dasboost::thread
wird destructor und Zuweisungsoperator rufendetach()
auf dem Thread - Objekt zerstört / zugewiesen. Bei einem C ++ 11-std::thread
Objekt wirdstd::terminate()
die Anwendung aufgerufen und abgebrochen.Um den Punkt über Nur-Verschieben-Parameter zu verdeutlichen, gilt Folgendes in C ++ 11 und überträgt den Besitz des
int
vom temporärenstd::unique_ptr
auf den Parameter,f1
wenn der neue Thread gestartet wird. Wenn Sie jedoch verwenden,boost::thread
funktioniert es nicht, da esboost::bind
intern verwendet wird, undstd::unique_ptr
kann nicht kopiert werden. Es gibt auch einen Fehler in der mit GCC bereitgestellten C ++ 11-Thread-Bibliothek, der verhindert, dass dies funktioniert, wie es auchstd::bind
in der dortigen Implementierung verwendet wird.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 weitgehend vollständige Implementierung der im
-std=c++0x
Modus verfügbaren C ++ 11-Thread-Bibliothek ).Wenn Ihr Compiler keine C ++ 11-Threads unterstützt, können Sie möglicherweise eine Drittanbieterimplementierung wie Just :: Thread erhalten , dies ist jedoch immer noch eine Abhängigkeit.
quelle
lock
/unlock
für Schreiber vs. 'lock_shared / entsperren_shared' für Leser). Mehrere Leser können lock_shared aufrufen, ohne zu blockieren, solange keine Autoren es verwenden.shared_mutex
Dokumente finden Sie unter boost.org/doc/libs/1_47_0/doc/html/thread/… . Sie sperren den Mutex entweder als freigegeben oder als exklusiv und verwenden dann die entsprechende Entsperrfunktion. Sie können dazu auch die RAII-Typen verwenden (verwendetshared_lock
eine gemeinsame Lesesperrelock_guard
undunique_lock
eine exklusive Sperre). Ich habe versucht, den Punkt über Nur-Verschieben-Typen zu klären.try_scoped_lock
Funktionalität von abgedecktstd::unique_lock
. Es gibt einen Konstruktor, der einen Mutex und verwendetstd::try_to_lock
und danntry_lock()
den Mutex anstelle von aufruftlock()
. Siehe stdthread.co.uk/doc/headers/mutex/unique_lock/…std::thread
ist weitgehend nachempfundenboost::thread
, mit einigen Unterschieden :Dies ist aus dem Jahr 2007, daher sind einige Punkte nicht mehr gültig:
boost::thread
hatnative_handle
jetzt eine Funktion und hat, wie Kommentatoren betonen,std::thread
keine Stornierung mehr.Ich konnte keine signifikanten Unterschiede zwischen
boost::mutex
und feststellenstd::mutex
.quelle
std::thread
hat keine Stornierung; das istboost::thread
es!interrupt()
für boost :: thread meinst ? Es scheint auch, dass es sich um einen ursprünglichen Vorschlag handelt, der sich seit 2007 geändert hat.Es gibt einen Grund, nicht zu migrieren
std::thread
.Wenn Sie statische Verknüpfungen verwenden,
std::thread
werden diese aufgrund der folgenden Fehler / Funktionen unbrauchbar:Wenn Sie anrufen
std::thread::detach
oderstd::thread::join
es zu einer Ausnahme oder einem Absturz führt,boost::thread
funktioniert dies in diesen Fällen in Ordnung.quelle
libpthread.a
. Bist du dir absolut sicher, was du sagst?Wl,--whole-archive -lpthread -Wl,--no-whole-archive
, siehe diese Antwort zum Beispiel stackoverflow.com/a/23504509/72178 . Aber es ist kein sehr einfacher Weg, sich mit einerlibpthread.a
schlechten Idee zu verbinden und sie auch als schlecht zu betrachten.Unternehmensfall
Wenn Sie Software für Unternehmen schreiben, die auf einer moderaten 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 erstellt werden muss, ist mein Vorschlag, sich davon fernzuhalten C ++ 11 insgesamt vorerst. Das bedeutet, dass Sie nicht verwenden können
std::thread
, und ich würde empfehlen, zu verwendenboost::thread
.Basic / Tech Startup Case
Wenn Sie für ein oder zwei Betriebssysteme schreiben, wissen Sie mit Sicherheit, dass Sie immer nur mit einem modernen Compiler erstellen müssen, der hauptsächlich C ++ 11 unterstützt (z. B. VS2015, GCC 5.3, Xcode 7), und Sie sind es noch nicht also abhängig von der Boost-Bibliothek
std::thread
könnte dann eine gute Option sein.Meine Erfahrung
Ich persönlich mag gehärtete, stark genutzte, hochkompatible, hochkonsistente Bibliotheken wie Boost im Vergleich zu einer sehr modernen Alternative. Dies gilt insbesondere für komplizierte Programmierthemen wie Threading. Außerdem habe ich lange Zeit große Erfolge mit
boost::thread
(und Boost im Allgemeinen) in einer Vielzahl von Umgebungen, Compilern, Threading-Modellen usw. erzielt. Wenn es meine Wahl ist, entscheide ich mich für Boost.quelle
Mit Visual Studio 2013
std::mutex
scheint sich das anders zu verhalten als dasboost::mutex
, was mir einige Probleme bereitete (siehe diese Frage ).quelle
In Bezug auf std :: shared_mutex in C ++ 17 hinzugefügt
Die anderen Antworten hier geben einen sehr guten Überblick über die Unterschiede im Allgemeinen. Es gibt jedoch mehrere Probleme mit
std::shared_mutex
dieser Boost-Lösung.Aufrüstbare Mutices. Diese fehlen in
std::thread
. Sie ermöglichen es einem Leser, ein Upgrade auf einen Writer durchzuführen, ohne dass andere Writer vor Ihnen einsteigen können . Mit diesen können Sie beispielsweise eine große Berechnung vorverarbeiten (z. B. eine Datenstruktur neu indizieren), während Sie sich im Lesemodus befinden, und dann auf Schreiben aktualisieren, um die Neuindizierung anzuwenden, während Sie die Schreibsperre nur für kurze Zeit gedrückt halten.Gerechtigkeit. Wenn Sie eine konstante
std::shared_mutex
Leseaktivität mit a haben , werden Ihre Autoren auf unbestimmte Zeit gesperrt. Dies liegt daran, dass ein anderer Leser immer Vorrang hat, wenn er mitkommt. Mit erhaltenboost:shared_mutex
alle Threads schließlich Priorität. (1) Weder Leser noch Schriftsteller werden verhungern.Das Wichtigste dabei ist, dass ein System mit sehr hohem Durchsatz ohne Ausfallzeiten und mit sehr hohen Konflikten
std::shared_mutex
niemals für Sie funktioniert, ohne manuell ein Prioritätssystem darauf aufzubauen.boost::shared_mutex
funktioniert sofort, obwohl Sie in bestimmten Fällen möglicherweise daran basteln müssen. Ich würde argumentieren, dass diesesstd::shared_mutex
Verhalten ein latenter Fehler ist, der darauf wartet, in den meisten Codes, die ihn verwenden, aufzutreten.(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.
quelle
Ich habe versucht, shared_ptr von std anstelle von boost zu verwenden, und ich habe 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 Wechsel zu boost :: shared_ptr sind alle Probleme verschwunden. Aktuelle Implementierungen von C ++ 11 sind noch nicht ausgereift.
Boost hat auch mehr Funktionen. Zum Beispiel bietet der Header in der Standardversion keinen Serializer für einen Stream (dh cout << Dauer). Boost hat viele Bibliotheken, die ihre eigenen usw. Äquivalente verwenden, aber nicht mit Standardversionen zusammenarbeiten.
Zusammenfassend lässt sich sagen, dass es sicherer ist, den Code so zu belassen, wie er ist, wenn Sie bereits eine Anwendung haben, die mit boost geschrieben wurde, anstatt sich um die Umstellung auf den C ++ 11-Standard zu bemühen.
quelle
shared_ptr
Destruktor muss nicht threadsicher sein. Es ist ein undefiniertes Verhalten, wenn ein Thread auf ein Objekt zugreift, während ein anderer Thread es zerstört. Wenn Sie der Meinung sind, dass Sie einen Fehler in GCCs shared_ptr gefunden haben, melden Sie ihn bitte , andernfalls verwenden Sie ihn mit der Wahrscheinlichkeit, dass Sie ihn falsch verwenden.