我最近一直在研究 Linux 内核,并回顾了大学操作系统课程的时代。
就像那时一样,我正在玩线程之类的东西。一直以来我一直假设线程是自动在多个核心上同时运行但我最近发现您实际上必须显式编写代码来处理多个核心。
那么单核上的多线程有什么意义呢?我能想到的唯一例子是在大学编写客户端/服务器程序时,但这似乎是一个弱点。
一直以来我一直假设线程是自动的
在多个核心上同时运行,但我最近发现
您实际上必须显式编写代码来处理多个核心。
对于任何广泛使用的现代操作系统来说,上述内容都是不正确的。例如,所有 Linux 的调度程序都会自动调度不同内核上的线程,甚至在必要时自动将线程从一个内核移动到另一个内核,以最大限度地提高内核利用率。有一些 API 允许您修改调度程序的行为,但这些 API 通常用于disable自动线程到核心调度,而不是启用它。
那么单核上的多线程有什么意义呢?
假设您有一个 GUI 程序,其目的是执行昂贵的计算(例如,渲染 3D 图像或 Mandelbrot 集),然后显示结果。假设这个计算在这个特定的 CPU 上需要 30 秒才能完成。如果您以显而易见的方式实现该程序,并且仅使用单个线程,那么在执行计算时,用户的 GUI 控件将在 30 秒内无响应 - 用户将无法对您的程序执行任何操作,并且可能无法用他的电脑做任何事情。由于用户期望 GUI 控件始终具有响应能力,因此这将是一种糟糕的用户体验。
另一方面,如果您使用两个线程(一个 GUI 线程和一个渲染线程)实现该程序,则用户将能够单击按钮、调整窗口大小、退出程序、选择菜单项等,即使在计算时也是如此正在执行,因为操作系统能够唤醒 GUI 线程并允许其在必要时处理鼠标/键盘事件。
当然,可以使用单线程编写此程序并保持其 GUI 响应能力,方法是编写单线程来执行几毫秒的计算,然后检查是否有可用于处理的 GUI 事件,并处理它们,然后返回进行更多计算,等等。但是,如果您以这种方式编写应用程序,那么您本质上是在应用程序中编写自己的(非常原始的)线程调度程序,那么为什么要重新发明轮子呢?
MacOS 的第一个版本被设计为在单核上运行,但没有真正的多线程概念。这迫使每个应用程序开发人员正确实现一些手动线程管理——即使他们的应用程序没有任何扩展计算,他们也必须明确指示何时使用 CPU,例如通过致电等待下一个事件 http://everything2.com/title/WaitNextEvent。多线程的缺乏使得 MacOS 的早期版本(MacOS-X 之前的版本)在多任务处理方面非常不可靠,因为只要一个编写得不好的应用程序就可能使整个计算机陷入瘫痪。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)