一对一多线程模型



在silberschatz的"操作系统概念"一书中,第4.3.2节说

一对一模型提供比多对一模型更多的并发性 通过允许另一个线程在线程进行阻塞时运行 系统调用。它还允许多个线程并行运行 多处理器。

我这里有两个问题:

  1. 如何阻止一个线程而另一个线程映射到内核线程上? 难道我们不知道,如果一个线程被阻塞,整个过程 用户级线程被阻止?
  2. 操作系统考虑用户级线程 仅作为一个线程。它不能分配给多个 处理器/内核。下面给出的行不是与此相矛盾吗? 想法?

    它还允许多个线程并行运行 多处理器

您对用户级线程和内核级线程的理解不正确,特别是您需要了解用户级线程如何映射到内核级线程。所以首先让我们定义一些术语

内核线程

由内核创建和管理的线程(可调度任务)。每个内核级线程都由一些数据结构表示,其中包含与线程相关的信息。在Linux的情况下,它是task_struct。内核线程是 CPU 调度程序考虑进行调度的唯一线程。

注意:内核线程有点用词不当,因为 Linux 内核不区分线程和进程,可调度任务可以更好地描述这个实体

用户线程

由内核级别的某个库(如 JVM)创建和管理的线程。创建这些线程的库负责管理哪个线程以及何时运行。

用户级到内核级映射

现在,您可以根据需要创建任意数量的用户级线程,但要执行它们,您需要创建一些内核级线程(task_struct)。内核级线程的创建可以通过多种方式完成

一对一模型

在这种情况下,每当您创建用户级线程时,您的库都会要求内核创建新的内核级线程。对于 Linux,您的库将使用克隆系统调用来创建内核级线程。

多对一模型

在这种情况下,您的库只创建一个内核级线程 (task_struct)。无论您创建多少个用户级线程,它们都共享相同的内核级线程,就像在单个核心 CPU 上运行的进程一样。要理解的一点是,这里的库非常类似于 CPU 调度程序,它在单个内核级线程上调度许多用户级线程。

现在回答您的问题

OS 仅将用户级线程视为一个线程。不可能 分配给多个处理器/内核。下面不是给出的行吗 与这个想法相矛盾?

如果您使用的是多对一模型,在这种情况下,所有用户级线程将只有一个内核级线程,因此它们不能在不同的 CPU 上运行。

但是,如果您使用的是一对一模型,那么每个用户级线程都有一个相应的内核级线程,可以单独调度,因此用户级线程可以在不同的 CPU 上运行,前提是您有多个 CPU。

你正在遭受一本令人困惑的书。

有真正的线程(又名内核线程,1 对 1 模型)和模拟线程(又名用户线程,多对 1 模型)。

有些书通过抛出一个假设的多对多模型来使这种情况更加混乱。

用户线程已过时。如今,任何值得一读的操作系统书籍都会以这种方式对待它们,并用历史术语来描述它们。

如何阻止一个线程而另一个线程映射到内核线程上?难道我们不知道如果一个线程被阻塞,该用户级线程的整个过程就会被阻塞吗?

您要么有用户线程,要么有内核线程。同时做到这两点的应用程序将被皇家搞砸。

OS 仅将用户级线程视为一个线程。它不能分配给多个处理器/内核。下面给出的行不是与这个想法相矛盾吗?

在过去,进程被认为是执行流和地址空间。没有线程。当线程变得必要时(主要是由于需要 Ada 支持),它们使用计时器进行模拟。线程的行为因操作系统而异。

在太监变体中,阻止调用会完全阻止该过程。因此,在模拟(用户)线程中,一个线程中的阻塞调用将阻塞所有线程。并非所有操作系统都是如此。

现在,进程是一个或多个执行流和一个地址空间。这就是你应该学习的;不是一堆技术喋喋不休。

一本用 1 对 1 或多对 1 模型来谈论线程的书只适合排列猫箱。

最新更新