【问题标题】:What is a "thread" (really)?什么是“线程”(真的)?
【发布时间】:2011-07-09 06:44:13
【问题描述】:

我一直在努力寻找一个好的定义,并了解线程到底是什么。

似乎我一定遗漏了一些明显的东西,但每次我读到线程是什么时,它几乎是一个循环定义,一个“线程是一个执行线程”或“一种划分运行任务的方法” ”。呃呃。嗯?

从我所读到的内容看来,线程并不是真正的某种东西,就像进程一样。它实际上只是一个概念。根据我对这种工作方式的理解,处理器为一个程序执行一些命令(这​​被称为 执行线程),然后当它需要切换到其他程序的处理时位,它将当前正在执行的程序的状态存储在某处(线程本地存储),然后开始执行其他程序的指令。来回。这样一来,线程实际上只是当前正在运行的程序的“执行路径之一”的概念。

与流程不同,流程确实是某种东西——它是资源等的集合体。

作为一个对我没有多大帮助的定义的例子。 . .

来自Wikipedia

“计算机科学中的线程是执行线程的缩写。线程是程序将自身划分(称为“拆分”)为两个或多个同时(或伪同时)运行的任务的一种方式。线程和进程一个操作系统与另一个操作系统不同,但一般来说,一个线程包含在一个进程中,同一进程中的不同线程共享相同的资源,而同一多任务操作系统中的不同进程则不共享。”

我说的对吗?错误的?什么是真正的线程?

编辑:显然线程也有自己的调用堆栈,所以这有点具体事情

【问题讨论】:

  • “过程”是一个抽象的术语。
  • 线程本地存储只是线程的调用栈吗?
  • 下面的答案是……抽象的。用更简单的术语(并掩盖一些细节):曾几何时,计算机程序一次只能做一件事。所以它做了A,然后是B,然后是C,然后......在现代系统中,这并不理想。例如,您想在下载文件的同时继续浏览网页。所以程序现在有一个或多个“线程”。每个“线程”一次只能做一件事,但不同的线程可以同时做事。线程 1 可以做 A,然后是 B,然后是 C;线程 2 可以执行 X,然后是 Y,然后是 Z。在 A 完成之前,B 无法启动,但 A 和 X 可以同时发生。
  • @eric 线程和进程之间的基本区别(也是最重要的区别)是两个或多个线程可以共享内存中的相同空间,即使用相同的资源,而两个进程必须存在于不同的内存空间。这有意义吗?

标签: multithreading process definition


【解决方案1】:

线程是可以执行的集合CPU)指令

但为了更好地理解线程是什么,需要一些计算机架构知识。

计算机所做的是遵循指令和操作数据。 RAM是保存指令和数据的地方,处理器使用这些指令对保存的数据进行操作。

CPU 有一些内部存储单元,称为寄存器。它可以使用存储在这些寄存器中的数字执行简单的数学运算。它还可以在 RAM 和这些寄存器之间移动数据。这些是可以指示 CPU 执行的典型操作的示例:

  • 将数据从内存位置#220 复制到寄存器#3
  • 将寄存器 #3 中的数字与寄存器 #1 中的数字相加。

CPU 可以执行的所有操作的集合称为指令集。指令集中的每个操作都分配了一个编号。计算机代码本质上是代表 CPU 操作的数字序列。这些操作以数字形式存储在 RAM 中。我们将输入/输出数据、部分计算和计算机代码一起存储在 RAM 中。

CPU 在一个永无止境的循环中工作,总是从内存中获取并执行一条指令。这个循环的核心是PC 寄存器,或程序计数器。它是一个特殊的寄存器,存储下一条要执行的指令的内存地址。

CPU 将:

  1. 在PC给定的内存地址处获取指令,
  2. 将 PC 加 1,
  3. 执行指令,
  4. 返回步骤 1。

可以指示 CPU 向 PC 写入新值,从而导致执行分支,或“跳转”到内存中的其他位置。这种分支可以是有条件的。例如,一条 CPU 指令可以说:“如果寄存器 #1 等于 0,则将 PC 设置为地址 #200”。这允许计算机执行如下操作:

if  x = 0
    compute_this()
else
    compute_that()

使用的资源来自Computer Science Distilled

【讨论】:

    【解决方案2】:

    为了正式定义线程,我们首先要了解线程运行的边界。

    当计算机程序从某个存储加载到计算机内存并开始执行时,它就变成了一个进程。一个进程可以由一个处理器或一组处理器执行。内存中的进程描述包含重要信息,例如跟踪程序中当前位置的程序计数器(即当前正在执行的指令)、寄存器、变量存储、文件句柄、信号等。

    线程是程序中可以独立于其他代码执行的一系列此类指令。该图显示了这个概念:

    线程位于相同的进程地址空间中,因此,进程内存描述中的大部分信息可以在线程之间共享。

    某些信息无法复制,例如堆栈(每个线程指向不同内存区域的堆栈指针)、寄存器和特定于线程的数据。 此信息足以允许线程独立于程序的主线程以及程序中的一个或多个其他线程进行调度

    运行多线程程序需要显式操作系统支持。幸运的是,大多数现代操作系统都支持线程,例如 Linux(通过 NPTL)、BSD 变体、Mac OS X、Windows、Solaris、AIX、HP-UX 等。操作系统可能使用不同的机制来实现多线程支持。

    Here,您可以找到有关该主题的更多信息。那也是我的信息来源。

    让我添加一个来自 Edward LeeSeshia 的来自 Introduction to Embedded System 的句子:

    线程是并发运行并共享内存空间的命令式程序。他们可以访问彼此的变量。该领域的许多从业者更狭义地使用术语“线程”来指代构建共享内存的程序的特定方式,[其他]广义地指代命令式程序并发运行并共享内存的任何机制。在这个广义上,线程在几乎所有微处理器上都以中断的形式存在,即使根本没有任何操作系统(裸机)。

    【讨论】:

    • 谢谢,这很有道理。
    【解决方案3】:

    我将使用 ABRAHAM SILBERSCHATZ、PETER BAER GALVIN 和 GREG GAGNE 所著《操作系统概念》一书中的大量文字以及我自己对事物的理解。

    流程

    任何应用程序都以文本(或代码)的形式驻留在计算机中。

    我们强调程序本身并不是一个进程。一个程序是一个 被动实体,例如包含存储在磁盘上的指令列表的文件 (通常称为可执行文件)。

    当我们启动一个应用程序时,我们会创建一个执行实例。这种执行实例称为进程。 编辑:(根据我的解释,类似于一个类和一个类的实例,一个类的实例是一个进程。)

    Google Chrome 就是一个流程示例。 当我们启动 Google Chrome 时,会产生 3 个进程:

    浏览器 进程负责将用户界面管理为 以及磁盘和网络 I/O。当创建一个新的浏览器进程时 Chrome 已启动。只创建一个浏览器进程。

    渲染器 进程包含用于渲染网页的逻辑。因此,他们 包含处理 HTML、Javascript、图像等的逻辑。 作为一般规则,为每个网站创建一个新的渲染器进程 在新选项卡中打开,因此可能有多个渲染器进程处于活动状态 同时。

    • 为每种类型的插件(例如 Flash 或 QuickTime)正在使用中。插件进程包含的代码 插件以及使插件能够 与关联的渲染器进程和浏览器通信 过程。

    线程

    要回答这个问题,我认为您应该首先了解处理器是什么。处理器是实际执行计算的硬件。 编辑:(计算,如添加两个数字,对数组进行排序,基本上执行已编写的代码)

    现在继续定义线程。

    线程是CPU利用率的基本单位​​strong>;它包括一个线程 ID、一个程序 计数器、寄存器集和堆栈。

    编辑:来自英特尔网站的线程定义:

    线程或执行线程是一个软件术语,表示可以通过单个 CPU 内核或由其处理的基本有序指令序列。

    因此,如果来自 Chrome 应用程序的 Renderer 进程对数字数组进行排序,则排序将在执行的线程/线程上进行。 (关于线程的语法让我感到困惑)

    我对事物的理解

    流程是一个执行实例。线程是通过 CPU 访问执行计算的实际工作人员。当一个进程有多个线程运行时,该进程提供公共内存。

    编辑: 我认为有助于提供更多上下文的其他信息

    所有现代计算机都有多个线程。计算机中的线程数取决于计算机中的内核数。

    并发计算

    来自维基百科:

    并发计算是一种计算形式,其中多个计算在重叠的时间段内同时执行,而不是顺序执行(一个在下一个开始之前完成)。这是系统的属性——可以是单个程序、计算机或网络——每个计算(“进程”)都有一个单独的执行点或“控制线程”。 >

    所以,我可以编写一个计算 4 个数字之和的程序:

    (1 + 3) + (4 + 5)
    

    在计算这个总和的程序中(这将是一个在执行线程上运行的进程)我可以派生另一个可以在不同线程上运行的进程来计算 (4 + 5) 并将结果返回给原始进程,而原始过程计算 (1 + 3) 的总和。

    【讨论】:

    • 这才是真正的答案
    • 帮助很大。这就是解释的样子。
    • 这个答案的一大价值在于它提供了一本参考书,如果需要,您可以在其中找到更多详细信息。谢谢@chatuur!
    【解决方案4】:

    线程只不过是一个带有执行规则的内存上下文(或者 Tanenbaum 更好的说法,资源分组)。这是一个软件结构。 CPU 不知道线程是什么(这里有些例外,有些处理器有硬件线程),它只是执行指令。

    内核引入了线程和进程的概念,以一种有意义的方式管理内存和指令顺序。

    【讨论】:

      【解决方案5】:

      线程是一个执行上下文,它是 CPU 执行指令流所需的所有信息。

      假设您正在阅读一本书,并且您现在想休息一下,但您希望能够回来并从您停止的确切位置继续阅读。实现这一目标的一种方法是记下页码、行号和字号。所以你看书的执行上下文就是这三个数字。

      如果你有一个室友,并且她正在使用相同的技术,她可以在你不使用的时候拿走这本书,然后从她停下的地方继续阅读。然后你可以把它拿回来,从你原来的位置恢复它。

      线程以相同的方式工作。 CPU 给您一种错觉,即它同时进行多项计算。它通过在每次计算上花费一些时间来做到这一点。它可以做到这一点,因为它对每个计算都有一个执行上下文。就像您可以与朋友共享一本书一样,许多任务可以共享一个 CPU。

      在更技术层面上,执行上下文(因此是线程)由 CPU 寄存器的值组成。

      最后:线程不同于进程。线程是执行的上下文,而进程是与计算相关的一堆资源。一个进程可以有一个或多个线程。

      澄清:与进程相关的资源包括内存页面(进程中的所有线程都拥有相同的内存视图)、文件描述符(例如,打开的套接字)和安全凭证(例如,用户的 ID)谁开始了这个过程)。

      【讨论】:

      • 一个更好的类比是将人等同于 CPU(两者都某事),并将书等同于地址空间(两者都存在)。这样,不同书籍中的书签就像不同进程中的线程。具有多个书签的单本书将类似于多线程进程,这就是人们通常所说的“线程”的意思。它适用于单处理器机器,但当您谈论多处理时,它会有点崩溃。没有人关心哪个 CPU 执行函数 f(),但它确实谁读了第 11 章。
      • @pwnall,非常感谢您为像我这样的其他人消化了困难的概念!多线程是否涉及多处理(或在多个 CPU 上并行运行一个进程,以防我使用错误的术语)?
      【解决方案6】:

      进程就像两个人使用两台不同的计算机,必要时使用网络共享数据。线程就像使用同一台计算机的两个人,他们不必明确共享数据,但必须小心轮流。

      从概念上讲,线程只是在同一地址空间中嗡嗡作响的多个工蜂。每个线程都有自己的堆栈、自己的程序计数器等,但进程中的所有线程共享相同的内存。想象一下两个程序同时运行,但它们都可以访问相同的对象。

      将此与流程进行对比。每个进程都有自己的地址空间,这意味着一个进程中的指针不能用于引用另一个进程中的对象(除非您使用共享内存)。

      我想要理解的关键是:

      • 进程和线程都可以“同时运行”。
      • 进程不共享内存(默认情况下),但线程与同一进程中的其他线程共享其所有内存。
      • 进程中的每个线程都有自己的堆栈和自己的指令指针。

      【讨论】:

      • 您说“进程不共享任何内容(默认情况下)”但在您的类比中,您说“进程就像两个人使用两台不同的计算机,必要时使用网络共享数据”所以他们确实分享了一些东西?
      • @committedandroider:好电话。我编辑了我的答案,说进程不共享内存(默认情况下),但线程共享所有内存。
      【解决方案7】:

      线程是处理器寄存器的一组独立值(对于单个内核)。由于这包括指令指针(又名程序计数器),它控制以什么顺序执行的内容。它还包括堆栈指针,它最好指向每个线程的唯一内存区域,否则它们会相互干扰。

      线程是受控制流(函数调用、循环、goto)影响的软件单元,因为这些指令在指令指针上运行,并且属于特定线程。线程通常根据某种优先级方案进行调度(尽管可以设计一个每个处理器核心一个线程的系统,在这种情况下,每个线程都在运行,不需要调度)。

      事实上,指令指针的值和存储在该位置的指令足以确定指令指针的新值。对于大多数指令,这只是将 IP 增加指令的大小,但控制流指令会以其他可预测的方式更改 IP。 IP 取值的序列形成了一条贯穿程序代码的执行路径,由此产生了“线程”这个名称。

      【讨论】:

      • +1。线程并不比一组寄存器值更“具体”。
      • 什么“价值观”?这些是什么?他们如何定义一个线程
      • @Richard:CPU 寄存器的确切列表取决于架构,但指令指针和堆栈指针几乎是通用的。他们定义了一个线程,当这个线程(一组寄存器值)被加载到处理器内核中时,该线程运行。处理器正在获取线程所需的指令并更新线程寄存器。当需要上下文切换时,处理器会将这组寄存器值保存到内存中并加载属于不同线程的一组值,通常作为中断服务逻辑的一部分。
      • 谢谢本。这很有帮助。
      • 嗨,谢谢@BenVoigt。像我这样的菜鸟可能会绊倒的一些澄清:“处理器寄存器”是什么意思? “指令指针”和“堆栈指针”是什么意思?
      【解决方案8】:

      不同系统和不同实现的答案差异很大,但最重要的部分是:

      1. 一个线程有一个独立的执行线程(即,您可以上下文切换离开它,然后返回,它会从原来的位置恢复运行)。
      2. 线程有生命周期(它可以由另一个线程创建,另一个线程可以等待它完成)。
      3. 它的附加包袱可能比“进程”少。

      除此之外:线程可以通过语言运行时在单个进程中实现,线程可以是协程,线程可以通过线程库在单个进程中实现,或者线程可以是内核构造。

      在几个现代 Unix 系统中,包括我最熟悉的 Linux,一切都是线程——进程只是线程的一种类型,共享相对较少与父级相关的事情(即,它有自己的内存映射、自己的文件表和权限等)阅读man 2 clone,尤其是标志列表,在这里真的很有启发性。

      【讨论】:

      • 只有当处理器从一个线程转到另一个线程时(无论是在同一个进程中还是在另一个进程中),上下文切换吗?
      【解决方案9】:

      这是摘自雅虎答案:

      线程是一种编码结构 不受架构的影响 应用。单一进程 经常可能包含多个 线程。线程也可以直接 互相交流,因为他们 共享相同的变量。

      进程是独立执行的 拥有自己状态的单位 信息。他们也用自己的 地址空间,只能交互 与其他过程通过 进程间通信机制。

      但是,简单地说,线程就像不同的“任务”。所以想想当你在做某事的时候,例如你在一张纸上写下一个公式。这可以被认为是一个线程。然后另一个线程是你在另一张纸上写别的东西。这就是多任务处理的用武之地。

      据说英特尔处理器具有“超线程”(AMD 也有),它意味着能够更好地执行多个“线程”或多任务。

      我不确定线程​​是如何处理的。我确实记得听说过处理器在它们之间来回切换,但我对此不是 100% 确定,希望其他人可以回答这个问题。

      【讨论】:

      • 英特尔处理器如何更好地处理多线程?对于单核,一次只能执行一个线程。我同意处理器来回走动。你真的不能做得更好吗?
      • 这是一种优化,可为某些用例提供更好的性能。您可以在此处阅读有关超线程的信息:en.wikipedia.org/wiki/Hyper-threading
      • 线程不像任务。任务是需要完成的工作单元。线程就像执行任务的代理。区别很重要,因为多线程程序中的一个常见比喻是,当需要执行某些任务时,哪个线程执行它并不重要。该比喻最好通过 线程池 来体现,它是一个管理 工作线程集合的对象。 当一个任务对象提交到线程池,可以选择池中的任何一个工作线程来执行任务。
      【解决方案10】:

      不幸的是,线程确实存在。线程是有形的东西。你可以杀死一个,而其他人仍然会运行。您可以生成新线程....虽然每个线程都不是它自己的进程,但它们在进程内单独运行。在多核机器上,可以同时运行 2 个线程。

      http://en.wikipedia.org/wiki/Simultaneous_multithreading

      http://www.intel.com/intelpress/samples/mcp_samplech01.pdf

      【讨论】:

      • 是什么让它成为“有形的东西”?只是存储在 TLS 及其调用堆栈中的数据吗?
      • 这不仅仅是一个理解的抽象......如果它真的只是一个伪装成多个线程来回运行的单个线程,那么OP是正确的,但是是的,我会说这些数据会让它变得有形。
      • 开导我。 . .那么答案是什么?
      • @Richard 不想进入关于语义的辩论,只是用我的回答来试图从概念上向 OP 澄清。
      • @richard TLS 是什么?
      猜你喜欢
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 2010-11-14
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多