该问题涉及多线程应用程序的输出,其中每个线程仅在标准输出上打印其 ID(用户分配的编号)。这里所有线程都具有相同的优先级并竞争 CPU 配额以便在标准输出上打印。然而,运行相同的应用程序足够多的次数将导致屏幕上打印的 ID 顺序不同。该顺序是由操作系统调度程序决定的,操作系统调度程序是一个软件,因此是确定性的。尽管如此,它的行为似乎是不确定的,这让我回到了最初的问题。
答案1
对于线程来说,这是 100% 正常的任何和所有操作系统。线程库的文档、您可能找到的任何示例和教程等都可能会强调这一点,因为当人们学习线程的技巧时,这常常会让他们感到困惑。
线程是默认的(并且根据定义)不同步。
这意味着除非您做出相反的安排(通过锁、信号量等),否则不要期望线程以任何特定顺序执行。 他们在做什么或你如何做并不重要思考根据他们正在做的事情等,它们“可能会发生”。 简而言之:不要以这种方式思考它们,这不是它们的本质,也不是它们的用途。不要费心想出诸如“我处于单用户模式,我试图让系统像水一样静止,因为......等等等等”这样的心理化,这是浪费时间,那里那样没什么可学的。水是不可避免的仍然不,液体就是这样。故事结局。继续前进并享受。
正如您所说,在您设置为几乎不执行任何操作的系统上执行几乎不执行任何操作的线程将导致调度程序负载较轻,但请注意,CPU 仍然全速运行,并且几乎不执行任何操作快速发生的情况并不一定比任何其他情况都更可预测。 调度程序并不旨在同步或可预测地排序线程和进程。 我真的真的真的希望我说的这不会激励你炮制一个更复杂和伪逻辑的实验,因为正如已经说过的,那是浪费时间,继续吧。
你能并且可能会同步它们,但请注意,这是一个微妙的技巧,首先要求您理解为什么它们不只是“自然地做到这一点”(线索:因为它们没有理由这样做,所以它们不这样做)。
“是什么造就了确定性操作系统似乎不确定性?”
也许流体动力学的类比并不那么愚蠢。流体似乎混沌——烟雾甚至看起来是有生命的——我相信数学、流体动力学和混沌理论的研究交叉。然而,大多数人可能不会对此感到震惊(“太棒了!什么会导致自然现象中的这种行为?也许这是上帝的证据!”......不),因为我们可以理解确定性规则(法则的法则)如何相互作用流体动力学)在一定范围内观察将产生只能粗略预测的结果(“好吧,水会从玻璃杯中溢出......”),因此实际上是混乱的或不确定的(桌子上溅起的图案)。即使那只是“很小的火”或一杯水,我们也认识到其中涉及数万亿个粒子的运动。
如果您曾经忙于循环使用计数器只是为了看看计算机的计数速度有多快,您就会知道它的数量级是数十亿每秒的次数。请记住,即使在“空闲”系统中,大多数不断发生的“次要”系统事件仍然比通过打印 ID 来衡量其活动的线程要重要得多(如果是这样的话)所有线程都在做。按照我们的流体类比,即使在我们看来“完全无风”的一天,烟雾仍然不会形成有序的柱(但我们可以更清楚地看到它自身的运动如何影响它)。
调度程序应该确保所有进程以平衡的方式运行(重力将确保水会溢出),但是,而不是一次给每个进程恰好 1 纳秒(这可能使您的实验更可预测)。这一切都很好,因为调度程序的作用不是同步任何东西,而是让一切以适当平衡的方式发生。这两个目标并不相同。当您真正开始同步时,您会发现同步虽然可以实现明显的平衡,但却是以效率为代价的。
此外,Linux 调度程序使用红黑树为了组织它的队列,它并不简单地在一个飞洛线(我怀疑任何现代通用调度程序都会这样做)。这意味着更大的复杂性因此,更多显然混乱的行为。
我不想鼓励你坚持你的固着,但如果你让线程执行一项更实质性的任务,一个实际上会让它们执行类似的事情时间做,并在空闲的系统上以几秒钟的时间偏移启动它们,那么实际上您将看到完全确定的结果。 只要记住这一点不是真正有效的同步手段 ——当风刮起来、水流汹涌时,你会看到混乱开始;)
“您知道有哪些研究研究这些事件对操作系统调度程序的影响吗?”
不,因为它没有什么真正神秘的,就像液体一样。调度程序实际上是完全确定性的,只是不是在您正在考虑的意义上或规模上。如果您在内核代码中放入一堆信息printk
并了解调度程序的算法,您将不会发现任何不确定性 - 一切都会按照预期的方式发生。
答案2
软件不可能比硬件更具确定性。首先,您有来自许多来源的随机中断(例如鼠标、键盘、网络、时钟、存储、操作系统后台任务)。
即使在程序执行期间完全禁用这些中断,80486 及更新版本的通用 x86 桌面硬件也具有明显的非确定性执行顺序。 (因此通常不适合许多实时任务,这也是 80386 在 Pentium 1 和 2 出现很久之后的 2007 年继续生产的原因。)必须牺牲硬件确定性才能以合理的成本获得吞吐量。这是由于缓存效应、同时多线程(超线程)、分支预测、乱序执行和管道传输造成的。确定性行为是 8 位 Arduino 比速度快得多的 Raspberry-Pi 更适合精确机器控制的原因。
默认情况下,Mainline Linux 是一个通用操作系统,具有通用调度程序,旨在实现良好的整体吞吐量和交互式任务的良好平均延迟。主线还可以与“软实时”调度一起使用,例如视频通话,您需要一定的延迟限制和良好的排序,但仍然可以容忍罕见的突发事件。
有一个实时补丁可以制作一个完全可抢占的硬实时 Linux 内核(甚至可以抢占/延迟/中断内核线程以支持用户任务。)这将允许将任务的延迟限制在硬件的偏差限制。这种硬限制要求通常会降低硬件的有效利用率并改变操作系统的行为。 (这就像在停车场保留一些停车位。它减少了最大平均车辆数量,但对于预留停车位的用户来说,停车时间现在是固定的。) RTL 内核是专业音乐录制的首选、机器控制、银行交易、精确传感器数据采样、医疗设备等。硬件选择将是开发考虑因素的核心部分,特别是如果您所需的最大(不是均值、中值或众数)延迟方差(不是总延迟)必须小于大约 500k 时钟周期。
至于普通的通用Linux调度程序。任务的默认调度使用动态优先级,它会在运行时根据 CPU 负载和实际任务行为稍微调整优先级。由于后台任务、不同的开始状态(例如执行开始时的缓存条件)和随机故障(例如导致任务赢得或输掉竞争的虚假中断请求),实际 CPU 负载和任务行为涉及大量变量。下一个时间片以及由此产生的调度级联效应。)
答案3
我从早期的 8 位开始就使用 PC,并且熟悉多种编程语言。我一次又一次地发现,Mint Cinnamon 的操作系统在做了一些应该有效的事情之后,却在后台做一些事情,但却扰乱了操作系统的深层功能。重新启动通常会有所帮助,但并非总是如此。我不得不说,最终 Windows 并不是更好,而是在更改系统提供的更改选项后发生的情况更可预测。熟悉过去的测试,我认为 Mint 没有按照应有的方式进行测试。