进程和线程之间有什么区别?


1640

进程和线程之间的技术区别是什么?

我感到像“过程”这样的词已被过度使用,并且还有硬件和软件线程。像Erlang这样的语言的轻量级进程怎么样?是否有确定的理由使用一个术语而不是另一个?



4
可能需要说每个操作系统对什么是“线程”或“进程”有不同的想法。一些主流的操作系统没有“线程”的概念,还有一些嵌入式操作系统只有“线程”。
尼尔

Answers:


1456

进程和线程都是独立的执行序列。典型的区别是(同一进程的)线程在共享内存空间中运行,而进程在单独的内存空间中运行。

我不确定您可能指的是“硬件”还是“软件”线程。线程是一种操作环境功能,而不是CPU功能(尽管CPU通常具有使线程有效的操作)。

Erlang使用术语“过程”,因为它没有公开共享内存的多程序模型。将它们称为“线程”将暗示它们具有共享内存。


56
硬件线程可能是指内核中的多个线程上下文(例如,超线程,SMT,Sun的Niagara / Rock)。这意味着重复的寄存器文件,指令通过流水线携带的多余位,以及其他更复杂的旁路/转发逻辑。
Matt J

4
@greg,我在线程中有一个疑问。让我考虑我有一个进程A,它在RAM中有一些空间。如果进程A创建了一个线程,则该线程还需要一些空间来执行。那么它会增加为进程A创建的空间的大小,还是为其他地方创建的线程的空间呢?那么虚拟空间过程是做什么的呢?如果我的问题不对,请纠正我。谢谢
duslabo 2012年

9
@JeshwanthKumarNK:创建一个新线程至少为新堆栈分配足够的内存。该内存由操作系统过程A.分配
格雷格Hewgill

24
这个答案似乎是错误的。如果进程和线程都是独立的执行序列,那么包含两个线程的进程将必须具有三个执行序列,这是不对的。只有一个线程是一个执行序列-进程是一个可以容纳一个或多个执行序列的容器。
David Schwartz

8
“硬件线程”是被赋予单独的硬件资源(单独的核心,处理器或超线程)的线程。“软件线程”是必须竞争相同处理能力的线程。
jpmc26

811

流程
每个流程都提供执行程序所需的资源。进程具有虚拟地址空间,可执行代码,系统对象的打开句柄,安全上下文,唯一进程标识符,环境变量,优先级类别,最小和最大工作集大小以及至少一个执行线程。每个进程都从单个线程(通常称为主线程)开始,但是可以从其任何线程中创建其他线程。

线程
线程是进程中可以安排执行的实体。进程的所有线程共享其虚拟地址空间和系统资源。另外,每个线程维护异常处理程序,调度优先级,线程本地存储,唯一的线程标识符以及系统将用于保存线程上下文直到被调度的一组结构。线程上下文包括线程进程的地址空间中的线程的计算机寄存器集,内核堆栈,线程环境块和用户堆栈。线程也可以具有自己的安全上下文,可用于模拟客户端。


在以下位置的Microsoft文档上可以找到此信息:关于进程和线程

Microsoft Windows支持抢先式多任务处理,这可以同时执行来自多个进程的多个线程。在多处理器计算机上,系统可以同时执行与计算机上处​​理器数量一样多的线程。


18
对于想知道您为什么不能同时格式化软盘的人:stackoverflow.com/questions/20708707/…–
Computernerd

7
@LuisVasconcellos-如果没有线程,则该进程将不执行任何操作。该过程只会将某些代码和程序状态加载到内存中。没什么用。就像有条没有任何车辆行驶的道路。
斯科特·

4
@LuisVasconcellos-很好。是的,您可以将线程视为在流程代码中移动并执行该代码中的指令的事物。
斯科特·

9
这个答案比公认的答案要好得多,因为它谈到了进程和线程的理想:它们应该是独立的事物,具有不同的关注点。事实是,大多数操作系统的历史可以追溯到线程发明之前,因此,在大多数操作系统中,即使随着时间的推移它们逐渐得到改善,这些问题仍然有些纠结。
所罗门慢速

4
@BKSpurgeon一个人给出的每一种解释,都必须使您的读者从一种理解的水平转到另一种层次。不幸的是,我无法为每个读者量身定制答案,因此必须假设一定的知识水平。对于那些不知道的人,他们可以进一步搜索我所使用的,他们不理解,不能理解的术语,直到达到他们确实理解的基点。我本来建议您提供自己的答案,但很高兴看到您已经拥有了。
斯科特·朗厄姆

301

处理:

  • 程序的执行实例称为进程。
  • 一些操作系统使用术语“任务”来指代正在执行的程序。
  • 进程始终存储在主存储器中,也称为主存储器或随机存取存储器。
  • 因此,过程被称为活动实体。如果重新启动计算机,它将消失。
  • 多个进程可能与同一程序相关联。
  • 在多处理器系统上,可以并行执行多个进程。
  • 在单处理器系统上,尽管没有实现真正的并行性,但应用了一种进程调度算法,并且该处理器被调度为一次执行一个进程,从而产生了并发的错觉。
  • 示例:执行“计算器”程序的多个实例。每个实例都称为一个过程。

线:

  • 线程是进程的子集。
  • 它被称为“轻量级进程”,因为它类似于真实进程,但在进程的上下文中执行并共享内核分配给该进程的相同资源。
  • 通常,一个进程只有一个控制线程–一次执行一组机器指令。
  • 进程也可以由同时执行指令的多个执行线程组成。
  • 多控制线程可以利用多处理器系统上可能的真正并行性。
  • 在单处理器系统上,应用线程调度算法,并安排处理器一次运行每个线程。
  • 进程中运行的所有线程共享相同的地址空间,文件描述符,堆栈和其他与进程相关的属性。
  • 由于进程的线程共享相同的内存,因此在进程内同步访问共享数据将获得空前的重要性。

我从知识探索中借用了以上信息博客


90
Kumar:据我所知,线程不共享同一堆栈。否则,将无法在每个代码上运行不同的代码。
Mihai Neacsu 2013年

27
是的,我认为@MihaiNeacsu是正确的。线程共享“代码,数据和文件”,并具有自己的“寄存器和堆栈”。我的操作系统课程中的幻灯片:i.imgur.com/Iq1Qprv.png
Shehaaz 2013年

这非常有用,因为它扩展了什么是线程和进程以及它们如何相互关联。我建议添加一个线程示例,尤其是因为有一个进程示例。好东西!
Smithers

1
Kquest.co.cc链接已死。
伊利亚·林恩

1
@ Rndp13问题只是使用“堆栈”一词,而不是“堆栈”。线程确实共享堆栈,因为堆栈只是虚拟内存的一部分,而线程共享所有虚拟内存。线程甚至可以隐藏其堆栈指针,并且可以由另一个线程恢复执行而不会出现任何问题。一个线程恰巧在某个特定时间执行一个堆栈并不意味着线程不共享堆栈,就像一个线程同时在一个文件描述符上运行并不意味着线程不共享文件描述符一样。
大卫·史瓦兹

127

首先,让我们看一下理论方面。您需要了解流程在概念上的含义,以了解流程与线程之间的区别以及它们之间的共享。

Tanenbaum 在2.2.2现代操作系统中的经典线程模型”中有以下内容:

流程模型基于两个独立的概念:资源分组和执行。有时将它们分开很有用;这是线程进入的地方。

他继续:

查看流程的一种方式是将相关资源组合在一起。进程的地址空间包含程序文本和数据以及其他资源。这些资源可能包括打开的文件,子进程,挂起的警报,信号处理程序,记帐信息等。通过以流程的形式将它们放在一起,可以更轻松地对其进行管理。进程具有的另一个概念是执行线程,通常简称为线程。该线程具有程序计数器,该计数器跟踪接下来要执行的指令。它具有寄存器,用于保存其当前的工作变量。它有一个堆栈,其中包含执行历史记录,每个调用但尚未返回的过程都有一帧。尽管线程必须在某些进程中执行,线程及其过程是不同的概念,可以分别处理。流程用于将资源分组在一起;线程是计划在CPU上执行的实体。

在下方,他提供了下表:

Per process items             | Per thread items
------------------------------|-----------------
Address space                 | Program counter
Global variables              | Registers
Open files                    | Stack
Child processes               | State
Pending alarms                |
Signals and signal handlers   |
Accounting information        |

让我们处理硬件多线程问题。传统上,CPU将支持单个执行线程,并通过单个程序计数器和一组寄存器来维护线程的状态。但是,如果出现缓存未命中怎么办?从主内存中获取数据需要花费很长时间,而在这种情况下,CPU只是闲置在那里。因此,有人想到了基本具有两组线程状态(PC +寄存器)的想法,以便另一个线程(可能在同一进程中,也许在不同进程中)可以在另一个线程正在等待主内存的同时完成工作。此概念有多种名称和实现,例如超线程和同步多线程(简称SMT)。

现在让我们看一下软件方面。基本上可以通过三种方式在软件端实现线程。

  1. 用户空间线程
  2. 内核线程
  3. 两者结合

实现线程所需要做的就是保存CPU状态并维护多个堆栈的能力,在许多情况下,这可以在用户空间中完成。用户空间线程的优势是超快速的线程切换,因为您不必陷入内核,并且可以按自己的方式调度线程。最大的缺点是无法阻止I / O(这将阻止整个进程及其所有用户线程),这是我们首先使用线程的主要原因之一。在许多情况下,使用线程阻止I / O可以大大简化程序设计。

除了将所有调度问题留给OS之外,内核线程还具有能够使用阻塞I / O的优势。但是每个线程切换都需要陷入内核,这可能相对较慢。但是,如果由于I / O阻塞而切换线程,这并不是真正的问题,因为I / O操作可能已经将您困在了内核中。

另一种方法是将两者结合在一起,每个内核线程具有多个用户线程。

因此,回到术语问题,您可以看到流程和执行线程是两个不同的概念,您选择使用哪个术语取决于您所讨论的内容。关于“轻量级过程”,我个人没有看到它的意义,因为它并没有真正传达出正在发生的事情以及术语“执行线程”。


4
出色的答案!它打破了很多行话和假设。但这确实使这条线显得很尴尬:“所以有人想到了基本上具有两组线程状态(PC +寄存器)的想法”-这里所说的“ PC”是什么?
Smithers

2
@Smithers PC是程序计数器或指令指针,它给出要执行的下一条指令的地址: en.wikipedia.org/wiki/Program_counter
Robert S. Barnes


为什么“堆栈”没有在“每个处理项目”下列出?进程和线程都有自己的堆栈。
stackoverflowuser2010

1
@ stackoverflowuser2010不仅只有线程具有堆栈。您所称的进程是具有单个执行线程的进程,并且具有堆栈的线程而不是进程。
罗伯特·S·巴恩斯

100

关于并发编程的更多解释

  1. 流程具有独立的执行环境。流程通常具有一套完整的私有基本运行时资源;特别是,每个进程都有自己的存储空间。

  2. 线程存在于一个进程中-每个进程至少有一个。线程共享进程的资源,包括内存和打开的文件。这样可以进行有效的通信,但可能会出现问题。

牢记普通人,

在计算机上,打开Microsoft Word和Web浏览器。我们称这两个过程

用Microsoft Word,您输入一些东西,它将自动保存。现在,您将观察到编辑和保存是并行进行的-在一个线程上进行编辑,然后在另一个线程上进行保存。


14
出色的答案,它使事情变得简单,并提供了一个示例,每个用户即使查看该问题也可以涉及。
Smithers

7
编辑/保存是一个进程内多个线程的一个很好的例子!

53

一个应用程序包含一个或多个进程。简单来说,一个过程就是一个执行程序。一个或多个线程在该进程的上下文中运行。线程是操作系统向其分配处理器时间的基本单位。线程可以执行过程代码的任何部分,包括当前由另一个线程执行的部分。光纤是执行单元,必须由应用程序手动调度。光纤在对其进行调度的线程的上下文中运行。

这里被盗。


在其他操作系统(例如Linux)上,两者在操作系统级别上没有实际区别,只是线程通常与父进程共享相同的内存空间。(因此,我表示
不满

1
很好的答案(尤其是在记账方面),因为它显示了两者之间的关系,并成为一个容易想到的“下一个问题”(关于纤维)。
Smithers

29

进程是代码,内存,数据和其他资源的集合。线程是在流程范围内执行的代码序列。您(通常)可以在同一进程中同时执行多个线程。


27

进程和线程的真实示例 这将为您提供有关线程和进程的基本概念 在此处输入图片说明

我从Scott Langham的Answer中借用了以上信息 -谢谢


25

处理:

  1. 过程是一个繁重的过程。
  2. 进程是一个单独的程序,具有单独的内存,数据,资源等。
  3. 使用fork()方法创建进程。
  4. 在过程之间进行上下文切换非常耗时。

示例:
说,打开任何浏览器(mozilla,Chrome,IE)。此时,新过程将开始执行。

线程数:

  1. 线程是轻量级进程,线程捆绑在进程内部。
  2. 线程具有共享的内存,数据,资源,文件等。
  3. 线程是使用clone()方法创建的。
  4. 线程之间的上下文切换不像Process那样耗时。

示例:
在浏览器中打开多个选项卡。


在Windows世界中,您是正确的,但是在Linux中,每个“线程”都是一个进程,并且同样“繁重”(或较轻)。
尼尔

22
  • 每个进程都是一个线程(主线程)。
  • 但是每个线程都不是一个进程。它是过程的一部分。

3
您能否进一步解释一下和/或提供一些证据?
Zim84

15

线程和进程都是OS资源分配的原子单位(即,有一个并发模型描述如何在它们之间分配CPU时间,以及拥有其他OS资源的模型)。有一个区别:

  • 共享资源(线程按照定义共享内存,除了堆栈和局部变量外,它们不拥有其他任何东西;进程也可以共享内存,但是有单独的机制,由操作系统维护)
  • 分配空间(进程的内核空间与线程的用户空间)

上面的Greg Hewgill关于“过程”一词的Erlang含义是正确的,这里讨论了为什么Erlang可以进行轻量级的过程。


13

进程和线程都是独立的执行序列。典型的区别是(同一进程的)线程在共享内存空间中运行,而进程在单独的内存空间中运行。

处理

是正在执行的程序。它具有文本部分,即程序代码,由程序计数器的值和处理器寄存器的内容表示的当前活动。它还包括包含临时数据(例如函数参数,返回的寻址变量和局部变量)的过程堆栈,以及包含全局变量的数据部分。进程还可以包括堆,该堆是在进程运行时动态分配的内存。

线

线程是CPU使用率的基本单位。它包括线程ID,程序计数器,寄存器集和堆栈。它与属于同一进程的其他线程共享它的代码段,数据段和其他操作系统资源,例如打开的文件和信号。

-摘自Galvin的操作系统


13

http://lkml.iu.edu/hypermail/linux/kernel/9608/0191.html

莱纳斯·托瓦尔兹(Linus Torvalds)(torvalds@cs.helsinki.fi)

1996年8月6日,星期二12:47:31 +0300(EET DST)

邮件排序方式:[日期] [主题] [主题] [作者]

下一条消息:Bernd P. Ziller:“回复:糟糕,get_hash_table”

上一条消息:Linus Torvalds:“回复:I / O请求订购”

Peter P. Eiserloh在1996年8月5日星期一写道:

我们需要保持线程概念的清晰。似乎有太多人将线程与进程混淆。以下讨论并不反映linux的当前状态,而是试图停留在较高级别的讨论中。

没有!

没有理由认为“线程”和“进程”是分开的实体。传统上就是这样,但是我个人认为这样做是一个重大错误。认为这种方式的唯一原因是历史包bag。

线程和进程实际上只是一件事:“执行上下文”。试图人为地区分不同情况只是自我限制。

“执行的上下文”,这里称为COE,只是该COE的所有状态的集合体。该状态包括CPU状态(寄存器等),MMU状态(页面映射),许可状态(uid,gid)和各种“通信状态”(打开文件,信号处理程序等)。传统上,“线程”和“进程”之间的区别主要是线程具有CPU状态(可能还有一些其他最小状态),而所有其他上下文都来自进程。但是,这只是 划分COE总体状态的一种方法,没有什么可以说是正确的方法。把自己限制在那种形象上只是愚蠢的。

Linux的想着这个问题的方法(和我想要的东西的工作方式)是有没有这样的事,作为一个“过程”或“线程”。只有COE的全部(在Linux中称为“任务”)。不同的COE可以彼此共享其上下文的一部分,并且该共享的一个子集是传统的“线程” /“进程”设置,但实际上应该仅将其视为子集(这是一个重要的子集,但重要性就在于此)不是来自设计,而是来自标准:我们显然也想在Linux上运行符合标准的线程程序。

简而言之:不要围绕线程/进程的思维方式进行设计。应该围绕COE的思维方式设计内核,然后pthreads 可以将受限的pthreads接口导出给想要使用该方式查看COE的用户。

就像当您认为COE而不是线程/进程时可能发生的情况的一个示例:

  • 您可以执行一个外部“ cd”程序,这在UNIX和/或进程/线程中是传统上不可能的(愚蠢的示例,但是您的想法是您可以拥有不限于传统UNIX的这类“模块” / threads设置)。做一个:

克隆(CLONE_VM | CLONE_FS);

子代:execve(“ external-cd”);

/ *“ execve()”将取消与VM的关联,因此我们使用CLONE_VM的唯一原因是使克隆动作更快* /

  • 您可以自然地执行“ vfork()”(它仅需最小限度的内核支持,但该支持完全适合CUA的思维方式):

克隆(CLONE_VM);

子:继续运行,最终execve()

母亲:等待执行

  • 您可以进行外部“ IO重传”:

克隆(CLONE_FILES);

子级:打开文件描述符等

妈妈:用fd的孩子打开vv。

以上所有工作都是因为您不受线程/进程思维方式的束缚。例如,以Web服务器为例,其中CGI脚本作为“执行线程”完成。您无法使用传统线程来做到这一点,因为传统线程总是必须共享整个地址空间,因此您必须链接您想在Web服务器本身中做的所有事情(“线程”无法运行另一个可执行文件)。

作为一个问题的“执行的情况下”这一思想,而不是,你的任务现在可以选择执行外部程序(=分离从父地址空间)等,如果他们想,也可以例如共享一切与家长除了为文件描述符(以便子“线程”可以打开很多文件而无需父级担心它们:当子“线程”退出时它们会自动关闭,并且不会用完父级中的fd) 。

例如,考虑一个线程化的“ inetd”。您需要低开销的fork + exec,因此可以使用Linux方式,而不是使用“ fork()”,而是编写多线程inetd,其中每个线程仅使用CLONE_VM创建(共享地址空间,但不共享文件)描述符等)。然后,如果孩子是外部服务(例如,rlogind),或者它是内部inetd服务(例如,echo,timeofday)之一,则可以执行该命令,然后退出。

您无法使用“线程” /“进程”来执行此操作。

莱纳斯


12

尝试从Linux内核的OS视图中回答

当程序启动到内存中时,它成为一个进程。进程具有其自己的地址空间,这意味着在内存中具有各种段,例如.text用于存储已编译代码的段,.bss用于存储未初始化的静态或全局变量等的段。
每个进程将具有自己的程序计数器和用户空间堆栈

在内核内部,每个进程将具有自己的内核堆栈(出于安全性问题与用户空间堆栈分开)和一个命名为的结构,该结构task_struct通常抽象为进程控制块,存储有关进程的所有信息,例如优先级,状态,(以及很多其他大块)。
一个进程可以有多个执行线程。

进入线程后,它们驻留在进程内部,并与创建线程时可以传递的其他资源(例如文件系统资源,共享挂起的信号,共享数据(变量和指令))一起共享父进程的地址空间。因此可以更快地进行上下文切换。

在内核内部,每个线程都有自己的内核堆栈以及task_struct定义线程的结构。因此,内核将同一进程的线程视为不同的实体,并且它们本身可以进行调度。同一进程中的线程共享一个称为线程组id(tgid)的通用ID ,也有一个称为进程ID(pid)的唯一ID 。


11

试图回答与Java世界有关的问题。

进程是程序的执行,但是线程是进程内的单个执行序列。一个进程可以包含多个线程。线程有时称为轻量级进程

例如:

示例1:JVM在单个进程中运行,并且JVM中的线程共享属于该进程的堆。这就是为什么多个线程可以访问同一对象的原因。线程共享堆并拥有自己的堆栈空间。这样一来,一个线程对方法及其局部变量的调用就可以使线程免受其他线程的影响。但是堆不是线程安全的,因此必须同步以确保线程安全。

示例2:程序可能无法通过读取按键来绘制图片。该程序必须充分注意键盘输入,并且一次不能处理多个事件的能力将导致麻烦。解决此问题的理想方法是同时无缝执行一个程序的两个或多个部分。线程使我们能够做到这一点。这里的“绘制图片”是一个过程,而读取按键是“子”过程(线程)。


1
好的答案,我喜欢它定义了它的范围(Java世界),并提供了一些适用的示例-包括一个(#2),任何必须提出原始问题的人都可以立即与之联系。
Smithers

9

线程和进程之间的区别?

进程是应用程序的执行实例,线程是进程内的执行路径。另外,一个进程可以包含多个线程。重要的是要注意一个线程可以执行一个进程可以做的任何事情。但是由于一个进程可以包含多个线程,所以一个线程可以被认为是“轻量级”进程。因此,线程和进程之间的本质区别是每个线程用于完成的工作。线程用于小型任务,而进程用于更多的“重量级”任务-基本上是应用程序的执行。

线程与进程之间的另一个区别是,同一进程内的线程共享相同的地址空间,而不同的进程则不共享。这允许线程读取和写入相同的数据结构和变量,并且还促进线程之间的通信。进程之间的通信(也称为IPC或进程间通信)非常困难且占用大量资源。

这是线程和进程之间差异的摘要:

  1. 线程比进程更容易创建,因为它们不需要单独的地址空间。

  2. 多线程需要仔细编程,因为线程共享数据结构,一次只能由一个线程修改。与线程不同,进程不会共享相同的地址空间。

  3. 线程被认为是轻量级的,因为它们使用的资源远少于进程。

  4. 流程彼此独立。由于线程共享相同的地址空间,因此它们是相互依赖的,因此必须谨慎行事,以防止不同的线程彼此踩踏。
    这实际上是上面陈述#2的另一种方式。

  5. 一个进程可以包含多个线程。


9

以下是我从The Code Project的一篇文章中得到的内容。我想它可以清楚地说明所有需要的内容。

线程是将工作负载拆分为单独的执行流的另一种机制。线程比进程轻。这意味着,与完整的过程相比,它提供的灵活性较差,但是由于操作系统的设置较少,因此启动速度更快。当一个程序包含两个或多个线程时,所有线程共享一个内存空间。为进程分配了单独的地址空间。所有线程共享一个堆。但是每个线程都有自己的堆栈。


1
除非从已经了解线程与进程的角度出发,否则不确定是否明确。添加它们之间的相互关系可能很有用。
Smithers

不清楚。这是否仅意味着一个进程及其线程?如果每个进程中都有许多具有多个线程的进程怎么办?所有这些线程都共享一个内存空间吗?在所有这些过程中?
绿色

9

处理:

流程基本上是一个正在执行的程序。它是一个活动实体。一些操作系统使用术语“任务”来指代正在执行的程序。进程始终存储在主存储器中,也称为主存储器或随机存取存储器。因此,过程被称为活动实体。如果重新启动计算机,它将消失。多个进程可能与同一程序相关联。在多处理器系统上,可以并行执行多个进程。在单处理器系统上,尽管没有实现真正的并行性,但应用了一种进程调度算法,并且该处理器被调度为一次执行一个进程,从而产生了并发的错觉。示例:执行“计算器”程序的多个实例。每个实例都称为一个过程。

线:

线程是进程的子集。它被称为“轻量级进程”,因为它类似于真实进程,但在进程的上下文中执行并共享内核分配给进程的相同资源。通常,一个进程只有一个控制线程–一次执行一组机器指令。进程也可以由同时执行指令的多个执行线程组成。多控制线程可以利用多处理器系统上可能的真正并行性。在单处理器系统上,应用线程调度算法,并安排处理器一次运行每个线程。进程中运行的所有线程共享相同的地址空间,文件描述符,堆栈和其他与进程相关的属性。由于进程的线程共享相同的内存,

ref- https://practice.geeksforgeeks.org/problems/difference-between-process-and-thread


听起来像一个进程中的节点并发与另一种语言的多线程并行性
user2734550 '19

从字面上看,这是从2010年的以下答案中复制粘贴的……
mc01

8

从面试官的角度来看,除了流程等显而易见的事情可能具有多个线程之外,我基本上只想听三件事:

  1. 线程共享相同的内存空间,这意味着线程可以从其他线程的内存访问内存。进程通常不能。
  2. 资源。资源(内存,句柄,套接字等)在进程终止而不是线程终止时释放。
  3. 安全。进程具有固定的安全令牌。另一方面,线程可以模拟不同的用户/令牌。

如果您想要更多,Scott Langham的回应几乎涵盖了所有方面。所有这些都是从操作系统的角度来看的。不同的语言可以实现不同的概念,例如任务,轻型线程等等,但是它们仅仅是使用线程(Windows上的线程)的方式。没有硬件和软件线程。有硬件和软件异常中断,或者有用户模式和内核线程


例如,当您说安全令牌时,您是说像在Linux上一样的用户凭证(用户名/密码)吗?

在Windows中,这是一个复杂的主题,安全令牌(实际上称为访问令牌)是一个很大的结构,其中包含访问检查所需的所有信息。该结构是在授权后创建的,这意味着没有用户名/密码,而是基于用户名/密码的SID /权限列表。更多细节在这里:msdn.microsoft.com/en-us/library/windows/desktop/...
AndreiM

8
  1. 线程在共享内存空间中运行,但是进程在单独的内存空间中运行
  2. 线程是一个轻量级进程,但是一个进程是一个重级进程。
  3. 线程是进程的子类型。

这感觉非常递归。如果扩展线程和进程之间的关系,也许会是一个更好的答案。
Smithers

7

对于那些更愿意通过可视化学习的人,这是我创建的一个方便使用的图表,用于解释进程和线程。
我使用了MSDN中的信息- 关于进程和线程

进程和线程


1
添加另一个进程只是为了了解多线程与多处理的比较可能会很有趣。
Bram Vanroy

6

来自嵌入式世界,我想补充一点,进程的概念仅存在于具有MMU(内存管理单元)的“大型”处理器(台式机CPU,ARM Cortex A-9)和支持使用MMU的操作系统(例如Linux)。对于小型/老式处理器和微控制器以及小型RTOS操作系统(实时操作系统)(例如freeRTOS),不支持MMU,因此不支持进程,而仅支持线程。

线程可以访问彼此的内存,并且它们是由操作系统以交错方式调度的,因此它们看起来可以并行运行(或者使用多核,它们实际上可以并行运行)。

另一方面,进程位于由MMU提供和保护的虚拟内存专用沙箱中。这很方便,因为它可以:

  1. 防止越野车过程使整个系统崩溃。
  2. 通过使其他过程数据不可见和不可访问来维护安全性。进程内部的实际工作由一个或多个线程负责。

6
  1. 基本上,线程是进程的一部分,没有进程线程将无法工作。
  2. 线程是轻量级的,而进程是重量级的。
  3. 进程之间的通信需要一些时间,而线程需要更少的时间。
  4. 线程可以共享相同的内存区域,而进程位于单独的内存中。

6

流程:正在执行的程序称为流程

线程:线程是一种功能,可根据“一个与另一个”的概念与程序的另一部分一起执行,因此线程是进程的一部分。


不错,尽管它引入了一个新概念(“一个彼此”),但对于提出这个问题的人来说可能是陌生的。
Smithers

帖子的格式设置为代码,但应为普通文本。
Heinrich

6

there,作为一名正在学习OS课程的本科生,我已经仔细阅读了几乎所有答案,但是我无法完全理解这两个概念。我的意思是大多数人都从某些OS书籍中读到了差异,即线程能够访问事务单元中的全局变量,因为它们利用了进程的地址空间。但是,新的问题提出了为什么要有进程,众所周知,我们已经知道线程相对于进程而言是更轻量级的。让我们通过使用从先前答案之一中摘录的图像来浏览以下示例

我们有3个线程同时处理一个单词文档,例如Libre Office。第一个通过下划线强调单词是否拼写来进行拼写检查。第二个接收并打印键盘上的字母。最后一个确实在每一次短时间内都保存了文档,以防万一出了问题而丢失了工作文档。在这种情况下,这3个线程不能是3个进程,因为它们共享一个公共内存,该内存是其进程的地址空间,因此都可以访问正在编辑的文档。因此,道路是“文件”一词,还有两个推土机,它们是线程,尽管图像中缺少其中之一。

在此处输入图片说明


5

在用Python(解释语言)构建包含多线程的算法时,我很惊讶地发现与我之前构建的顺序算法相比,执行时间并没有改善。为了理解产生此结果的原因,我做了一些阅读,并相信我所学的内容提供了一个有趣的上下文,从中可以更好地理解多线程与多进程之间的区别。

多核系统可能会行使多个执行线程,因此Python应该支持多线程。但是Python不是编译语言,而是解释语言1。这意味着必须对程序进行解释才能运行,并且解释程序在开始执行之前并不了解该程序。但是,它确实知道Python的规则,然后它动态地应用这些规则。那么,Python中的优化必须主要是解释器本身的优化,而不是要运行的代码。这与诸如C ++之类的编译语言相反,并且对Python中的多线程具有影响。具体来说,Python使用全局解释器锁来管理多线程。

另一方面,编译语言是编译好的。对该程序进行“整体”处理,首先根据其句法定义对其进行解释,然后将其映射到与语言无关的中间表示形式,最后链接到可执行代码中。此过程可以高度优化代码,因为在编译时都可用。在创建可执行文件时可以定义各种程序交互和关系,并且可以做出关于优化的可靠决策。

在现代环境中,Python的解释器必须允许多线程,而且这必须既安全又高效。这就是解释语言与编译语言之间的差异进入画面的地方。解释器必须不打扰来自不同线程的内部共享数据,同时优化处理器在计算中的使用。

如前几篇文章所述,进程和线程都是独立的顺序执行,主要区别在于,进程的多个线程之间共享内存,而进程隔离其内存空间。

在Python中,全局解释器锁保护数据免受不同线程的同时访问。它要求在任何Python程序中任何时候都只能执行一个线程。另一方面,可以运行多个进程,因为每个进程的内存与任何其他进程都是隔离的,并且进程可以在多个内核上运行。


1 Donald Knuth在“计算机编程艺术:基础算法”中很好地解释了解释性例程。


4

同一进程中的线程共享内存,但是每个线程都有自己的堆栈和寄存器,并且线程将特定于线程的数据存储在堆中。线程永远不会独立执行,因此与进程间通信相比,线程间通信要快得多。

进程永远不会共享相同的内存。当子进程创建时,它将复制父进程的内存位置。通过使用管道,共享内存和消息解析来完成进程通信。线程之间的上下文切换非常慢。


4

到目前为止,我找到的最佳答案是Michael Kerrisk的“ Linux编程接口”

在现代UNIX实现中,每个进程可以具有多个执行线程。设想线程的一种方法是共享相同的虚拟内存以及一系列其他属性的一组进程。每个线程执行相同的程序代码,并共享相同的数据区和堆。但是,每个线程都有自己的堆栈,其中包含局部变量和函数调用链接信息。[LPI 2.12]

这本书非常清晰;朱莉娅·埃文斯在清理如何Linux组真的在工作中提到它的帮助这篇文章


这似乎直接自相矛盾。有一部分说一个进程可以有多个线程。下一部分说一个线程是一组共享虚拟内存的进程。我看不出这两个事情怎么都可以成立。
大卫·史瓦兹

这是我的阅读方式:丢弃第一句话中的“拥有”一词。从术语上讲,剩下的就是1)单线程和2)线程组,为方便起见,这称为进程。这是我对Kerrisk在此之后的看法。
扎克·瓦伦塔

我想他想说的是,如果您习惯于旧的UNIX视图,进程是操作系统计划的,那么一组线程就像一组进程,只是它们共享很多东西。
大卫·史瓦兹

对!好的表达方式。
扎克·瓦伦塔

3

示例1:JVM在单个进程中运行,并且JVM中的线程共享属于该进程的堆。这就是为什么多个线程可以访问同一对象的原因。线程共享堆并拥有自己的堆栈空间。这样一来,一个线程对方法及其局部变量的调用就可以使线程免受其他线程的影响。但是堆不是线程安全的,因此必须同步以确保线程安全。


3

它们几乎相同...但是关键的区别在于,在上下文切换,工作负载等方面,线程是轻量级的,而进程是重量级的。


您能否扩大答案?
Fiver 2014年

3
线程是一个子进程,它们在一个进程内共享诸如代码,数据,文件之类的公共资源。而两个进程却不能共享资源(如果一个进程(父进程)派生出另一个进程(子进程),则例外情况是它们可以共享资源。),需要给CPU提供较高的有效负载,而在此上下文中线程要轻得多。尽管两者都具有相同的条件。方案,请考虑由于I / 0阻塞了单个线程进程,因此整个1将转到等待状态,但是当多线程进程被I / O阻塞时,则只有1个与I / O有关的线程将被阻塞。
Nasir Ul Islam Butt 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.