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!?!
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.
You can then use it as a regular
std::cout
, from any thread:The object collect data as a regular
std::ostringstream
. As soon the coma is reached, the object is destroyed and flush all collected information.The accepted answer is correct. However it is nice to separate concerns:
std::cout
in a thread safe manner.Here is a utility I use that just concentrates on collecting arguments to
std::cout
and streaming them out under astatic std::mutex
:This code can be reused for streams other than
std::cout
, but the above is specialized to just targetstd::cout
. With this yourPrinter::exec()
can now be significantly simplified:Now, not only will your
Printer
usecout
in a threadsafe manner, and has been simplified (e.g. doesn't need to maintain its ownmutex
forcout
), but all of your other types and functions can also usecout
and all interoperate together safely. Theprint
function itself now maintains themutex
, and that fact is encapsulated away from all ofprint
's clients.The threads are using different
mutex
instances as themutex
is a local variable in theexec()
function so locking themutex
is pointless as each thread will be locking its ownmutex
resulting in no synchronization between the threads. The samemutex
instance must be used by the threads to achieve synchronization.To correct in the posted code, make the
mutex
a member variable. However, if anotherPrinter
object was created then there would be no synchronization between threads that used differentPrinter
instances. In this case, themutex
would need to be astatic
member variable to ensure synchronization:To ensure a
mutex
is always released, regardless if a function exits normally or via an exception, usestd:lock_guard
:You may consider a global
std::mutex cout_mutex;
(somewhere in your namespaces), which is used to protectedstd::cout
output. Make sure you usestd::lock<std::mutex>
(so you cannot forget to unlock the mutex and for exception safety).