有这样一段人为的代码,输出流故意不受互斥锁保护
#include <iostream>
#include <string_view>
#include <thread>
void print(std::string_view message)
{
for (int i = 0;i < 10000;++i) {
std::cout << message;
}
}
int main()
{
std::thread t1(print, "hello\n");
std::thread t2(print, "aloha\n");
t1.join();
t2.join();
return 0;
}
输出是某种随机的
...
hello
hello
aloha
hello
aloha
...
但是为什么字是作为一个整体输出的,没有和这样的字符混淆,这haelohallo是否意味着输出流缓冲区受到互斥锁的保护,不允许多个线程写入,或者是安排在其他一些棘手的方式?
标准([iostreams.threadsafety])告诉我们:
但是对于标准流明确声明([iostream.objects.overview]):
免费翻译:
因此,仅为
cin/cout/提供同步cerr。对他们来说,保证字符在输入/输出过程中不会消失/重复,但是,严格来说,这并不能保证即使输出整行,它们也不会被交错,尽管事实上这被证明是大多数实现的案例。还值得考虑以下形式的结构:在几乎所有的实现中都会产生意想不到的效果。
对于所有其他流(文件/字符串等),所有这些都是未定义的行为,并且像往常一样,可能导致任何事情:从正确操作到输出中的数据消失/重复/流对象损坏、自燃和恶魔从鼻子里飞出来。
严格来说,使用互斥锁不是必须的,但在大多数标准线程的实现中,是的。因为 通常加上标准流是 Sishnyh 的包装器(实际上,标准暗示了这样的实现),然后具体取决于 libc 的实现。这就是在 glibc、uclibc、newlib 和 BSD libc 中使用互斥锁或类似结构的方式(当然,如果 libc 本身编译时支持多线程。)。
对于文件和字符串流,不需要同步。所以它不在弯曲的 libstdc ++ 中,尽管在所有列出的 libc 中,C 文件流默认以与标准文件相同的方式同步。
正如评论中已经指出的那样,在 C ++ 20 中,为了充分写入流,他们将添加
osyncstream.感谢@dIm0n指出原始答案中的错误。