mit std :: cout in mehreren Threads

9

Ich schreibe ein einfaches Programm zum Testen von Thread in C ++ 11, aber std::cout funktioniert nicht wie erwartet.

%Vor%

einige der Ergebnisse:

%Vor%

Ich habe Mutex zum Sperren von Threads verwendet, sodass ich nicht verstehen kann, warum zwei Threads std::cout gleichzeitig ausführen. Es scheint mir sehr verwunden. Kann irgendjemand erklären, was passiert!?!

    
Omid 16.08.2013, 15:45
quelle

4 Antworten

21

Die Threads verwenden verschiedene mutex Instanzen, da mutex eine lokale Variable in der Funktion exec() ist. Das Sperren von mutex ist daher sinnlos, da jeder Thread seine eigene Sperre setzt mutex , was zu keiner Synchronisation zwischen den Threads führt. Die gleiche mutex -Instanz muss von den Threads verwendet werden, um eine Synchronisation zu erreichen.

Um den geposteten Code zu korrigieren, machen Sie mutex zu einer Mitgliedsvariablen. Wenn jedoch ein anderes Printer -Objekt erstellt wurde, gab es keine Synchronisierung zwischen Threads, die unterschiedliche Printer -Instanzen verwendeten. In diesem Fall müsste mutex eine static -Membervariable sein, um die Synchronisation sicherzustellen:

%Vor%

Um sicherzustellen, dass ein mutex immer freigegeben wird, verwenden Sie %, unabhängig davon, ob eine Funktion normal oder über eine Ausnahme beendet wird. co_de% :

%Vor%     
hmjd 16.08.2013, 15:47
quelle
11

Die angenommene Antwort ist korrekt. Es ist jedoch schön, Bedenken zu trennen:

  1. Sie müssen eine Möglichkeit haben, in std::cout threadsicher zu drucken.
  2. Sie müssen Objekte / Funktoren / Funktionen erstellen, um sie in Threads auszuführen und zu starten.

Hier ist ein Dienstprogramm, das ich verwende, das sich darauf konzentriert, Argumente für std::cout zu sammeln und sie unter einem static std::mutex :

zu streamen %Vor%

Dieser Code kann für andere Streams als std::cout wiederverwendet werden, aber das obige ist darauf spezialisiert, nur std::cout zu targetieren. Damit kann Ihre Printer::exec() nun wesentlich vereinfacht werden:

%Vor%

Nun wird nicht nur Ihre Printer cout threadsicherer verwenden und wurde auch vereinfacht (zB muss nicht ihre eigene mutex für cout beibehalten), sondern all Ihre anderen Typen und Funktionen können auch cout verwenden und alle zusammen sicher zusammenarbeiten. Die Funktion print behält nun mutex bei, und diese Tatsache wird von allen Clients von print gekapselt.

    
Howard Hinnant 16.08.2013 20:40
quelle
3

Ich teile den Trick von Nicolás, gegeben in Diese Frage finde ich eleganter als die Implementierung von Howard Hinnant. Die Idee ist, ein temporäres ostringstream-Objekt zu erstellen und den Schutzcode auf den Destruktor zu setzen.

%Vor%

Sie können es dann als reguläres std::cout von jedem Thread verwenden:

%Vor%

Das Objekt sammelt Daten als reguläres std::ostringstream . Sobald das Koma erreicht ist, wird das Objekt zerstört und alle gesammelten Informationen werden gelöscht.

    
Conchylicultor 11.01.2017 23:58
quelle
1

Sie können eine globale std::mutex cout_mutex; (irgendwo in Ihren Namespaces) in Betracht ziehen, die verwendet wird, um std::cout output zu schützen. Stellen Sie sicher, dass Sie std::lock<std::mutex> verwenden (Sie können also nicht vergessen, den Mutex und die Ausnahmesicherheit zu entsperren).

    
Walter 16.08.2013 17:44
quelle