在多线程程序上,控制台上的 printf 和重定向到文件的顺序不同
on multi-threaded program printf on console and redirection to file have different order
我正在编写一个显示带时间戳的哲学家用餐的程序。每个数字表示我创建的线程。
这是我的代码的一部分:
i = -1;
while (++i < num_philos)
{
error = pthread_create(&philos[i].tid, NULL, dining, &philos[i]);
if (error)
return (release_rscs(init_val.forks, init_val.start, init_val.last_meals));
}
i = -1;
while (++i < num_philos)
pthread_detach(philos[i].tid);
当我像往常一样在控制台上打印时,它的顺序乱七八糟:
...
[1ms] 42 is eating
[0ms] 18 take right fork
[1ms] 18 is eating
[0ms] 26 take left fork
[1ms] 26 take right fork
...
但是当我将输出重定向到文件时,顺序更符合我的预期:
...
[1ms] 172 is eating
[1ms] 174 take left fork
[1ms] 174 take right fork
[1ms] 174 is eating
[2ms] 176 take left fork
[2ms] 176 take right fork
[2ms] 176 is eating
...
不仅顺序不同,性能也有所提升。
为什么他们不同?是线程相关还是缓冲区相关?
当多个线程 运行 时,程序内函数的执行顺序(相对于彼此)变得很难预测,因为它取决于 OS 的调度程序,在任何特定时刻可用的核心数量,其他任务可能同时 运行,每个线程的量子长度,月相等等等等。因此很难给出关于为什么事物以特定顺序打印的任何一般规则;您可能能够深入分析特定系统(硬件、OS、编译器版本等)并找出答案,但您发现的任何东西都可能无法推广到其他系统,因此几乎不值得付出努力。
至于控制台与文件的性能,请考虑将某些内容“打印”到控制台 window 需要与 window 管理器进程交互,呈现大量像素,(通常)滚动在终端 window 内向上像素等。与简单地将输出数据写入系统 RAM 中的缓冲区相比,这是相当多的工作(由于文件系统缓存,通常是“写入文件” “就用户可见的性能而言,实际上包括......将数据实际发送到磁盘通常发生在很久以后,通常在程序完成之后)。 Windows' DOS 提示在这方面似乎特别慢(我怀疑由于 historical/backwards-compatibility 原因,它的内部工作不是最佳的)。正是这种开销差异(以及您的程序在幕后交互的接口的不同性质)可能解释了不同的行为。
我正在编写一个显示带时间戳的哲学家用餐的程序。每个数字表示我创建的线程。
这是我的代码的一部分:
i = -1;
while (++i < num_philos)
{
error = pthread_create(&philos[i].tid, NULL, dining, &philos[i]);
if (error)
return (release_rscs(init_val.forks, init_val.start, init_val.last_meals));
}
i = -1;
while (++i < num_philos)
pthread_detach(philos[i].tid);
当我像往常一样在控制台上打印时,它的顺序乱七八糟:
...
[1ms] 42 is eating
[0ms] 18 take right fork
[1ms] 18 is eating
[0ms] 26 take left fork
[1ms] 26 take right fork
...
但是当我将输出重定向到文件时,顺序更符合我的预期:
...
[1ms] 172 is eating
[1ms] 174 take left fork
[1ms] 174 take right fork
[1ms] 174 is eating
[2ms] 176 take left fork
[2ms] 176 take right fork
[2ms] 176 is eating
...
不仅顺序不同,性能也有所提升。 为什么他们不同?是线程相关还是缓冲区相关?
当多个线程 运行 时,程序内函数的执行顺序(相对于彼此)变得很难预测,因为它取决于 OS 的调度程序,在任何特定时刻可用的核心数量,其他任务可能同时 运行,每个线程的量子长度,月相等等等等。因此很难给出关于为什么事物以特定顺序打印的任何一般规则;您可能能够深入分析特定系统(硬件、OS、编译器版本等)并找出答案,但您发现的任何东西都可能无法推广到其他系统,因此几乎不值得付出努力。
至于控制台与文件的性能,请考虑将某些内容“打印”到控制台 window 需要与 window 管理器进程交互,呈现大量像素,(通常)滚动在终端 window 内向上像素等。与简单地将输出数据写入系统 RAM 中的缓冲区相比,这是相当多的工作(由于文件系统缓存,通常是“写入文件” “就用户可见的性能而言,实际上包括......将数据实际发送到磁盘通常发生在很久以后,通常在程序完成之后)。 Windows' DOS 提示在这方面似乎特别慢(我怀疑由于 historical/backwards-compatibility 原因,它的内部工作不是最佳的)。正是这种开销差异(以及您的程序在幕后交互的接口的不同性质)可能解释了不同的行为。