Why is std :: cout dumped to the stream but printf isn't?
I'm starting to learn threads in the C ++ 11 standard and I've tried a very basic program that creates 10 threads, attaches them, and then exits. In the stream function, I tried to print the index of the for loop in which I create the streams, for example:
std::vector<std::thread> threads;
for(int i = 0; i < 10; i++)
{
threads.push_back(std::thread([i](){ printf("Thread #%d\n", i); }));
}
And this gives the result expected from a parallel program, threads are executed out of order:
Thread #0
Thread #2
Thread #1
Thread #3
Thread #4
Thread #5
Thread #6
Thread #7
Thread #8
Thread #9
But when I try to do the same using std::cout
and std::endl
, I get this:
Thread #0
Thread #Thread #2
Thread #3
Thread #9
1
Thread #8
Thread #4
Thread #5
Thread #7
Thread #6
Why does this happen with std::cout
but not with printf
?
source to share
You haven't provided your std :: cout code.
threads.push_back(std::thread([i](){ printf("Thread #%d\n", i); }));
But if I assume that you changed your code to:
threads.push_back(std::thread([i](){ std::cout << "Thread #" << i << std::endl; }));
It is significantly different in two respects:
The version printf
only has one call for the print libraries .:
printf("Thread #%d\n", i);
operator<<
has three different calls to print libraries
operator<<(std::cout, "Thread #");
operator<<(std::cout, i);
operator<<(std::cout, std::endl);
// note for the pedantic the use of functions here is for illustration purposes.
Assuming the print library has some sort of lock inside, the version printf
will provide you with a row for each thread. While the version operator<<
can be unloaded between calls.
I wouldn't bet on any version, even with an internal lock. The print section is probably short enough that there is little chance of seeing an interrupt there, and you may not have noticed it yet.
Try:
threads.push_back(std::thread([i]()
{ std::stringstream msg;
msg << "Thread #" << i << "\n";
std::cout << msg.rdbuf();
}));
source to share
As far as I know, anticipatory behavior is not guaranteed. Let me assume that you end the line in std :: cout with std :: endl. std :: endl does more than just add '\ n', it also removes the internal buffer, which in my experience is a protected action between threads. If you replace std :: endl with "\ n", it should also mix output between streams. Moreover, if you are writing very large strings to std :: cout, you can force buffer overflow and dumping if std :: cout, in which case the output can be triggered as well.
source to share