using std::cout in multiple threads
Solution 1
The threads are using different mutex
instances as the mutex
is a local variable in the exec()
function so locking the mutex
is pointless as each thread will be locking its own mutex
resulting in no synchronization between the threads. The same mutex
instance must be used by the threads to achieve synchronization.
To correct in the posted code, make the mutex
a member variable. However, if another Printer
object was created then there would be no synchronization between threads that used different Printer
instances. In this case, the mutex
would need to be a static
member variable to ensure synchronization:
class Printer
{
public:
//...
private:
static std::mutex mtx_;
};
std::mutex Printer::mtx_;
To ensure a mutex
is always released, regardless if a function exits normally or via an exception, use std:lock_guard
:
std::lock_guard<std::mutex> lock(m); // 'm' locked, and will be
// unlocked when 'lock' is destroyed.
std::cout<< "Hello " << std::this_thread::get_id() << std::endl;
std::chrono::milliseconds duration( 100 );
std::this_thread::sleep_for( duration );
Solution 2
The accepted answer is correct. However it is nice to separate concerns:
- You need a way to print to
std::cout
in a thread safe manner. - You need to create objects/functors/functions to run in threads and launch them.
Here is a utility I use that just concentrates on collecting arguments to std::cout
and streaming them out under a static std::mutex
:
#include <iostream>
#include <mutex>
std::ostream&
print_one(std::ostream& os)
{
return os;
}
template <class A0, class ...Args>
std::ostream&
print_one(std::ostream& os, const A0& a0, const Args& ...args)
{
os << a0;
return print_one(os, args...);
}
template <class ...Args>
std::ostream&
print(std::ostream& os, const Args& ...args)
{
return print_one(os, args...);
}
std::mutex&
get_cout_mutex()
{
static std::mutex m;
return m;
}
template <class ...Args>
std::ostream&
print(const Args& ...args)
{
std::lock_guard<std::mutex> _(get_cout_mutex());
return print(std::cout, args...);
}
This code can be reused for streams other than std::cout
, but the above is specialized to just target std::cout
. With this your Printer::exec()
can now be significantly simplified:
void exec()
{
print("Hello ", std::this_thread::get_id(), '\n');
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
Now, not only will your Printer
use cout
in a threadsafe manner, and has been simplified (e.g. doesn't need to maintain its own mutex
for cout
), but all of your other types and functions can also use cout
and all interoperate together safely. The print
function itself now maintains the mutex
, and that fact is encapsulated away from all of print
's clients.
Solution 3
I'm sharing the trick from Nicolás given in this question that I find to be more elegant than Howard Hinnant implementation. The idea is to create a temporary ostringstream object and put the protection code on the destructor.
/** Thread safe cout class
* Exemple of use:
* PrintThread{} << "Hello world!" << std::endl;
*/
class PrintThread: public std::ostringstream
{
public:
PrintThread() = default;
~PrintThread()
{
std::lock_guard<std::mutex> guard(_mutexPrint);
std::cout << this->str();
}
private:
static std::mutex _mutexPrint;
};
std::mutex PrintThread::_mutexPrint{};
You can then use it as a regular std::cout
, from any thread:
PrintThread{} << "val = " << 33 << std::endl;
The object collect data as a regular std::ostringstream
. As soon the coma is reached, the object is destroyed and flush all collected information.
Solution 4
You may consider a global std::mutex cout_mutex;
(somewhere in your namespaces), which is used to protected std::cout
output. Make sure you use std::lock<std::mutex>
(so you cannot forget to unlock the mutex and for exception safety).
Related videos on Youtube
uchar
Napoleon Hill: A quitter never wins and a winner never quits.
Updated on January 13, 2020Comments
-
uchar over 4 years
I write a simple program for testing Thread in c++11 but
std::cout
doesnt work as I expect.class Printer { public: void exec() { mutex m; m.lock(); cout<<"Hello "<<this_thread::get_id()<<endl; chrono::milliseconds duration( 100 ); this_thread::sleep_for( duration ); m.unlock(); } }; int main() { Printer printer; thread firstThread([&printer](){ while(1) printer.exec(); }); thread secondThread([&printer](){ while(1) printer.exec(); }); firstThread.join(); secondThread.join(); }
some of the results :
Hello 11376 Hello 16076 Hello 16076 Hello Hello 11376 16076 Hello 11376 ,....
I used mutex for locking threads so I cant understand why two threads are executing
std::cout
at the same time. It seams very weired to me.Can any one explain what is happening!?!-
bames53 over 10 yearsOnce you implement the solution provided in the answer you should also move to using
lock_guard
s rather than manual lock/unlock calls. And don't bother flushing (e.g., withendl
); just use '\n'.
-
-
Casey over 10 yearsFix is to declare
mutex
withstatic
storage duration. ... or that. -
hmjd over 10 years@Casey, or a member variable as the threads are using the same
Printer
instance. -
Casey over 10 years@hjmd I would prefer
static
in this case to correspond to the scope ofstd::cout
. That way it will keep working when some maintenance programmer down the line creates anotherPrinter
in some other function. -
user1284631 over 9 yearsunique_lock would be better in this case, because allows unlock-ing just after sending data to cout and before entering sleep (there is no good in holding the mutex during the sleep).
-
Jan Christoph Uhde over 7 yearsprint is a template function. I think you could end up with more than one mutex.
-
Howard Hinnant over 7 years@JanChristophUhde: Excellent observation! And it only took 3 years for someone to notice! :-) Fixed. Thanks.
-
Parker over 5 yearsHere is a slight refinement of this answer with a test case.
-
Jim Fischer about 5 yearsIn your example usage of PrintThread, the `std::endl' manipulator could (should?) be replaced by '\n' since you're writing to an ostringstream-dervied object. Note that when the ~PrintThread() destructor is invoked the "this" object is flushed when the base class std::ostringstream destructor is called, so there's no need to "manually" flush the PrintThread object via std::endl. And in your ~PrintThread() destructor method it might be worthwhile to flush the cout stream after writing "this->str()" to cout--i.e., std::cout << this->str() << std::flush;.