[英]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. 我开始学习C ++ 11标准中的线程,我正在尝试一个非常基本的程序,它创建10个线程,加入它们然后退出。 In the thread function, I tried to print out the index of the for loop that I'm creating the threads in, like this:
在线程函数中,我试图打印出我正在创建线程的for循环的索引,如下所示:
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: 但是当我尝试使用
std::cout
和std::endl
做同样的事情时,我得到了这个:
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
? 为什么这与
std::cout
发生但不与printf
?
You did not show your std::cout code. 你没有显示你的std :: cout代码。
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
版本只有一次打印库:
printf("Thread #%d\n", i);
The operator<<
has three distinct calls to the printing libraries operator<<
对打印库有三个不同的调用
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. 假设打印库内部有某种锁定,
printf
版本将为每个线程提供一行。 While the operator<<
version may be preempted between calls. 虽然
operator<<
版本可能在呼叫之间被抢占。
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();
}));
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结束std :: cout中的行。 std::endl does more then just adding '\\n' it also flushes the internal buffer which from my experience is a protected action between threads.
std :: endl做了更多然后只是添加'\\ n'它还刷新内部缓冲区,根据我的经验,这是一个线程之间受保护的操作。 If you replace std::endl with '\\n' it should also mix up output between threads.
如果用'\\ n'替换std :: endl,它也应该在线程之间混合输出。 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.
如果你在你的std :: cout中写了很长的行,你可能会强制缓冲区溢出,如果是std :: cout则刷新,在这种情况下输出也可能混淆。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.