Mertcan Ekiz
Mertcan Ekiz

Reputation: 711

Why is std::cout preempted in a thread but printf is not?

I am starting to learn threads in the C++11 standard and I was trying out a very basic program which creates 10 threads, joins them and then exits. In the thread function, I tried to print out the index of the for loop that I'm creating the threads in, like this:

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 produces an output expected from a concurrent program, the threads execute 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 thing 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 is this happening with std::cout but not with printf?

Upvotes: 3

Views: 1125

Answers (2)

Loki Astari
Loki Astari

Reputation: 264669

You did not show your std::cout code.

threads.push_back(std::thread([i](){ printf("Thread #%d\n", i); }));

But if I assume you changed the code to:

threads.push_back(std::thread([i](){ std::cout << "Thread #" << i << std::endl; }));

There is considerable different in the two:

The printf version has only one call to the printing libraries.:

printf("Thread #%d\n", i);

The operator<< has three distinct calls to the printing 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 printing library has some sort of lock internally the printf version will give you a line for each thread. While the operator<< version may be preempted between calls.

I would not bet on any version even having an internal lock. The printing section is probably just short enough that observing an interrupt there has a small probability and thus you may not have observed it yet.

Try:

threads.push_back(std::thread([i]()
{  std::stringstream msg;
   msg << "Thread #" << i << "\n";
   std::cout << msg.rdbuf();
}));

Upvotes: 6

Oncaphillis
Oncaphillis

Reputation: 1908

As far as I know the preempted behaviour is not guaranteed Let me assume you end the line in std::cout with std::endl. std::endl does more then just adding '\n' it also flushes the internal buffer which from my experience is a protected action between threads. If you replace std::endl with '\n' it should also mix up output between threads. Further more if you write very long lines into your std::cout you may force a buffer overrun and a flush if std::cout and in that case output may also be mixed up.

Upvotes: 0

Related Questions