进程和线程有啥区别?
Posted
技术标签:
【中文标题】进程和线程有啥区别?【英文标题】:What is the difference between a process and a thread?进程和线程有什么区别? 【发布时间】:2010-09-17 01:26:40 【问题描述】:进程和线程的技术区别是什么?
我觉得像“进程”这样的词被过度使用了,而且还有硬件和软件线程。像Erlang 这样的语言的轻量级进程怎么样?是否有明确的理由使用一个术语而不是另一个?
【问题讨论】:
相关:***.com/questions/32294367/… 这可能保证说每个操作系统对什么是“线程”或“进程”都有不同的想法。一些主流操作系统没有“线程”的概念,也有一些嵌入式操作系统只有“线程”。 TLDR:同级“线程”(在大多数操作系统中)共享相同的虚拟地址空间、相同的套接字和打开的文件、所有相同的资源。另一方面,“进程”是相互隔离/保护的,它们不共享任何内容,除非它们明确要求共享某些特定的东西。在同时具有“进程”和“线程”的操作系统中,进程通常可以被视为一个或多个线程以及它们共享的所有资源的容器。 【参考方案1】:进程和线程都是独立的执行序列。典型的区别是(同一进程的)线程在共享内存空间中运行,而进程在不同的内存空间中运行。
我不确定您所指的“硬件”和“软件”线程是什么。线程是一种操作环境特性,而不是 CPU 特性(尽管 CPU 通常具有使线程高效的操作)。
Erlang 使用术语“进程”,因为它没有公开共享内存多道程序模型。称它们为“线程”意味着它们具有共享内存。
【讨论】:
硬件线程可能是指一个内核中的多个线程上下文(例如 HyperThreading、SMT、Sun 的 Niagara/Rock)。这意味着重复的寄存器文件、通过流水线的指令携带的额外位以及更复杂的旁路/转发逻辑等等。 @greg,我在线程中有一个疑问。让我考虑一下我有一个进程 A,它在 RAM 中有一些空间。如果进程A创建了一个线程,该线程也需要一些空间来执行。那么它会增加为进程 A 创建的空间的大小,还是增加在其他地方创建的线程的空间?那么这个虚拟空间过程创造了什么?如果我的问题是错误的,请纠正我。谢谢 @JeshwanthKumarNK:创建一个新线程至少会为新堆栈分配足够的内存。此内存由进程 A 中的操作系统分配。 这个答案似乎是错误的。如果进程和线程都是独立的执行序列,那么包含两个线程的进程将必须具有三个执行序列,这是不对的。只有一个线程是一个执行序列——一个进程是一个容器,可以容纳一个或多个执行序列。 “硬件线程”是被赋予单独硬件资源(单独的核心、处理器或超线程)的线程。 “软件线程”是必须竞争相同处理能力的线程。【参考方案2】:流程 每个进程都提供执行程序所需的资源。进程具有虚拟地址空间、可执行代码、系统对象的打开句柄、安全上下文、唯一进程标识符、环境变量、优先级、最小和最大工作集大小以及至少一个执行线程。每个进程都由一个线程启动,通常称为主线程,但可以从它的任何线程创建额外的线程。
话题 线程是进程中可以调度执行的实体。一个进程的所有线程共享它的虚拟地址空间和系统资源。此外,每个线程都维护异常处理程序、调度优先级、线程本地存储、唯一线程标识符以及系统将用于保存线程上下文直到被调度的一组结构。线程上下文包括线程的机器寄存器集、内核堆栈、线程环境块和线程进程地址空间中的用户堆栈。线程也可以有自己的安全上下文,可用于模拟客户端。
此信息可在此处的 Microsoft Docs 中找到:About Processes and Threads
Microsoft Windows 支持抢先式多任务处理,这会产生从多个进程同时执行多个线程的效果。在多处理器计算机上,系统可以同时执行与计算机上的处理器一样多的线程。
【讨论】:
对于想知道为什么不能同时格式化软盘的人:***.com/questions/20708707/… @LuisVasconcellos - 如果没有线程,那么进程不会做任何事情。该过程只会将一些代码和程序状态加载到内存中。用处不大。这就像一条没有车辆行驶的道路。 这个答案比公认的答案要好得多,因为它讨论了进程和线程的理想:它们应该是具有不同关注点的独立事物。事实是,大多数操作系统的历史可以追溯到线程的发明之前,因此,在大多数操作系统中,这些问题仍然有些纠缠不清,即使随着时间的推移它们正在慢慢改善。 非常尊重先生,这个答案是对那些已经知道的人的参考,对那些不知道的人没有帮助。它读起来很像***条目。 @BKSpureon 给出的每一个解释,你都必须把你的读者从一个层次的理解提升到一个新的层次。不幸的是,我不能为每个读者量身定制答案,因此必须假设一定程度的知识。对于那些不知道的人,他们可以进一步搜索我使用的他们不理解的术语,不是吗,直到他们达到他们确实理解的基点。我打算建议你提供自己的答案,但很高兴看到你已经有了。【参考方案3】:流程:
程序的执行实例称为进程。 某些操作系统使用术语“任务”来指代正在执行的程序。 进程始终存储在主内存中,也称为主内存或随机存取内存。 因此,进程被称为活动实体。如果机器重新启动,它就会消失。 多个进程可能与同一个程序相关联。 在多处理器系统上,可以并行执行多个进程。 在单处理器系统上,虽然没有实现真正的并行性,但应用了进程调度算法,处理器被调度为一次执行每个进程,从而产生并发错觉。 示例: 执行“计算器”程序的多个实例。每个实例都称为一个进程。主题:
线程是进程的子集。 它被称为“轻量级进程”,因为它类似于真正的进程,但在进程的上下文中执行并共享内核分配给进程的相同资源。 通常,一个进程只有一个控制线程——一次执行一组机器指令。 一个进程也可以由同时执行指令的多个执行线程组成。 多线程控制可以利用多处理器系统上的真正并行性。 在单处理器系统上,应用线程调度算法,处理器被调度为一次运行每个线程。 在一个进程中运行的所有线程共享相同的地址空间、文件描述符、堆栈和其他与进程相关的属性。 由于进程的线程共享相同的内存,同步访问进程内的共享数据变得前所未有的重要。以上信息是从Knowledge Quest! blog借来的。
【讨论】:
Kumar:据我所知,线程不共享同一个堆栈。否则就不可能在每一个上运行不同的代码。 是的,我认为@MihaiNeacsu 是对的。线程共享“代码、数据和文件”并拥有自己的“寄存器和堆栈”。我的操作系统课程幻灯片:i.imgur.com/Iq1Qprv.png 这非常有用,因为它扩展了线程和进程是什么以及它们如何相互关联。我建议添加一个线程示例,特别是因为有一个用于进程的示例。好东西! Kquest.co.cc 链接已失效。 @Rndp13 问题只是使用了“stack”这个词而不是“stacks”。线程确实共享堆栈,因为堆栈只是虚拟内存的一部分,线程共享所有虚拟内存。线程甚至可以隐藏它们的堆栈指针,并且可以由另一个线程恢复执行而没有问题。一个线程恰好在某个特定时间执行一个堆栈并不意味着线程不共享堆栈,就像一个线程同时操作文件描述符这一事实并不意味着线程不共享文件描述符.【参考方案4】:首先,让我们看一下理论方面。您需要从概念上了解进程是什么,以了解进程和线程之间的区别以及它们之间共享的内容。
我们在 Tanenbaum 的 Modern Operating Systems 3e 的 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 |
让我们处理hardware multithreading 问题。传统上,CPU 将支持单个执行线程,通过单个program counter (PC) 和一组寄存器来维护线程的状态。但是当缓存未命中时会发生什么?从主内存中获取数据需要很长时间,而此时 CPU 只是闲置在那里。所以有人想到基本上有两组线程状态(PC + 寄存器),以便另一个线程(可能在同一个进程中,可能在不同的进程中)可以在另一个线程等待主内存时完成工作。这个概念有多种名称和实现方式,例如Hyper-threading和simultaneous multithreading(简称SMT)。
现在让我们看看软件方面。线程在软件端的实现基本上有三种方式。
-
用户空间线程
内核线程
两者的结合
实现线程所需的只是保存 CPU 状态和维护多个堆栈的能力,这在许多情况下可以在用户空间中完成。用户空间线程的优势是超快速的线程切换,因为您不必陷入内核,并且能够按照您喜欢的方式调度线程。最大的缺点是无法进行阻塞 I/O(这将阻塞整个进程及其所有用户线程),这是我们首先使用线程的重要原因之一。在许多情况下,使用线程阻塞 I/O 极大地简化了程序设计。
除了将所有调度问题留给操作系统之外,内核线程还具有能够使用阻塞 I/O 的优势。但是每个线程切换都需要陷入内核,这可能相对较慢。但是,如果您因为 I/O 阻塞而切换线程,这并不是真正的问题,因为 I/O 操作可能已经将您困在内核中。
另一种方法是将两者结合起来,多个内核线程每个都有多个用户线程。
回到你的术语问题,你可以看到进程和执行线程是两个不同的概念,你选择使用哪个术语取决于你在说什么。关于“轻量级进程”这个术语,我个人并不理解其中的意义,因为它并不能真正传达正在发生的事情以及“执行线程”这个术语。
【讨论】:
出色的答案!它打破了许多行话和假设。不过,这确实让这条线显得很尴尬:“所以有人想到基本上有两组线程状态(PC + 寄存器)”——这里提到的“PC”是什么? @Smithers PC 是程序计数器或指令指针,它给出了下一条要执行的指令的地址:en.wikipedia.org/wiki/Program_counter 我知道你在那里做了什么。 ***.com/questions/1762418/process-vs-thread/… '最大的缺点是不能做阻塞I/O'作者的意思是说有可能但是我们不正常做还是说阻塞io的实际实现根本不可能? 我一直认为在等待IO的同时执行其他进程的能力叫做乱序执行。【参考方案5】:更多关于并发编程的解释
一个进程有一个独立的执行环境。一个进程通常有一套完整的、私有的基本运行时资源;特别是,每个进程都有自己的内存空间。
线程存在于一个进程中——每个进程至少有一个。线程共享进程的资源,包括内存和打开的文件。这有助于高效但可能存在问题的沟通。
一个让普通人记住的例子:
在您的计算机上,打开 Microsoft Word 和网络浏览器。我们称这两个进程。
在 Microsoft Word 中,您键入内容会自动保存。现在,您已经观察到编辑和保存是并行进行的——在一个线程上编辑并在另一个线程上保存。
【讨论】:
出色的答案,它使事情变得简单,并为每个用户提供了一个示例,即使查看问题也可能涉及到。 编辑/保存是一个进程内多线程的一个很好的例子! 可能编辑和保存是不同的过程。【参考方案6】:一个应用程序由一个或多个进程组成。用最简单的术语来说,一个进程就是一个正在执行的程序。一个或多个线程在进程的上下文中运行。线程是操作系统分配处理器时间的基本单位。线程可以执行进程代码的任何部分,包括当前正在由另一个线程执行的部分。纤程是必须由应用程序手动调度的执行单元。 Fiber 在调度它们的线程的上下文中运行。
从here窃取。
【讨论】:
在其他操作系统上,比如Linux,两者在操作系统层面没有实际区别,只是线程通常与父进程共享相同的内存空间。 (因此我投反对票) 很好的答案(尤其是在信用方面),因为它显示了两者之间的关系,并且可以很容易地理解为“下一个问题”(关于纤维)。【参考方案7】:进程是代码、内存、数据和其他资源的集合。线程是在进程范围内执行的代码序列。您可以(通常)在同一个进程中同时执行多个线程。
【讨论】:
【参考方案8】:流程:
-
流程是一个重量级的流程。
进程是一个独立的程序,具有独立的内存、数据、资源等。
进程是使用 fork() 方法创建的。
进程之间的上下文切换非常耗时。
示例: 比如说,打开任何浏览器(mozilla、Chrome、IE)。此时新进程将开始执行。
主题:
-
线程是轻量级进程。线程捆绑在进程内部。
线程具有共享内存、数据、资源、文件等。
线程是使用 clone() 方法创建的。
线程之间的上下文切换不像进程那样耗时。
【讨论】:
在 Windows 世界中你是对的,但在 Linux 中,每个“线程”都是一个进程,并且同样“重”(或轻)。【参考方案9】:进程和线程的真实示例 这将为您提供有关线程和进程的基本概念
我从 Scott Langham 的回答中借用了上述信息 - 谢谢
【讨论】:
【参考方案10】: 每个进程都是一个线程(主线程)。 但是每个线程都不是一个进程。它是流程的一部分(实体)。【讨论】:
您能否进一步解释一下和/或提供一些证据?【参考方案11】:线程和进程都是 OS 资源分配的原子单元(即,有一个并发模型描述 CPU 时间如何在它们之间分配,以及拥有其他 OS 资源的模型)。有区别:
共享资源(线程根据定义共享内存,除了堆栈和局部变量外,它们不拥有任何东西;进程也可以共享内存,但有一个单独的机制,由操作系统维护) 分配空间(进程的内核空间与线程的用户空间)上面的 Greg Hewgill 对 Erlang 中“进程”一词的含义是正确的,here 讨论了为什么 Erlang 可以轻量级处理进程。
【讨论】:
【参考方案12】:http://lkml.iu.edu/hypermail/linux/kernel/9608/0191.html
莱纳斯·托瓦兹 (torvalds@cs.helsinki.fi)
1996 年 8 月 6 日星期二 12:47:31 +0300 (EET DST)
消息排序方式:[日期][主题][主题][作者]
下一条消息:Bernd P. Ziller:“Re: Oops in get_hash_table”
上一条消息:Linus Torvalds:“Re:I/O 请求排序”
1996 年 8 月 5 日星期一,Peter P. Eiserloh 写道:
我们需要保持一个清晰的线程概念。太多人 似乎将线程与进程混淆了。以下讨论 不反映linux当前的状态,而是一个 尝试保持高水平的讨论。
不!
没有理由认为“线程”和“进程”是 单独的实体。这就是传统上的做法,但我 个人认为这样想是大错特错。唯一的 这样想的理由是历史包袱。
线程和进程实际上只是一件事:一个“上下文 执行”。试图人为区分不同的情况只是 自我限制。
“执行环境”,在此称为 COE,只是集团 该 COE 的所有状态。该状态包括 CPU 之类的东西 状态(寄存器等),MMU 状态(页面映射),权限状态 (uid, gid) 和各种“通信状态”(打开文件、信号 处理程序等)。传统上,“线程”和“线程”之间的区别 “进程”主要是线程具有 CPU 状态(+ 可能 其他一些最小状态),而所有其他上下文都来自 过程。然而,这只是 一种 划分 COE 总状态的方法,没有什么可以说它是正确的方法。限制自己 那种形象简直就是愚蠢。
Linux 对此的思考方式(以及我希望事情发生的方式)是 没有“进程”或“线程”之类的东西。有 只有整个 COE(Linux 称为“任务”)。不同的COE 可以彼此共享部分上下文,并且其中一个 子集 共享是传统的“线程”/“进程”设置,但是 真的应该被视为只是一个子集(它是一个重要的子集,但 这种重要性不是来自设计,而是来自标准:我们显然 想在 Linux 上运行符合标准的线程程序 也)。
简而言之:不要围绕线程/进程的思维方式进行设计。这 内核应该围绕COE的思维方式设计,然后 pthreads library 可以将有限的 pthreads 接口导出给用户 谁想使用这种方式查看 COE。
作为一个例子,当您将 COE 视为可能时 反对线程/进程:
您可以执行外部“cd”程序,这在 UNIX 和/或进程/线程中传统上是不可能的(愚蠢的示例,但想法 是你可以拥有不限于这些类型的“模块” 传统的 UNIX/线程设置)。做一个:克隆(CLONE_VM|CLONE_FS);
child: execve("external-cd");
/* "execve()" 将解除 VM 的关联,所以我们唯一的原因是 使用 CLONE_VM 是为了让克隆行为更快 */
您可以自然地执行“vfork()”(它需要最少的内核支持,但这种支持非常适合 CUA 的思维方式):克隆(CLONE_VM);
child:继续运行,最终execve()
妈妈:等待执行
您可以执行外部“IO 守护程序”:克隆(CLONE_FILES);
child:打开文件描述符等
妈妈:使用孩子打开的fd和vv。
上述所有工作都是因为您不受线程/进程的束缚 思维方式。以 Web 服务器为例,其中 CGI 脚本作为“执行线程”完成。你不能这样做 传统线程,因为传统线程总是要共享 整个地址空间,所以你必须链接你曾经的所有东西 想在网络服务器本身做(一个“线程”不能运行另一个 可执行)。
将此视为“执行上下文”问题,您的 任务现在可以选择执行外部程序(= 将 来自父母的地址空间)等,如果他们愿意,或者他们可以 示例与文件的父 except 共享所有内容 描述符(以便子“线程”可以打开大量文件,而无需 父母需要担心它们:它们会自动关闭 子“线程”退出,并且它不会用完父级中的 fd)。
例如,考虑一个线程化的“inetd”。你想要低开销 fork+exec,所以用 Linux 的方式你可以代替使用“fork()” 您编写一个多线程 inetd,其中创建每个线程 只是 CLONE_VM(共享地址空间,但不共享文件描述符 等等)。如果它是外部服务(rlogind, 例如),或者它可能是内部 inetd 服务之一 (echo, timeofday) 在这种情况下,它只是做它的事情并退出。
“线程”/“进程”无法做到这一点。
莱纳斯
【讨论】:
【参考方案13】:试图回答这个与 Java 世界有关的问题。
进程是程序的执行,而线程是进程内的单个执行序列。一个进程可以包含多个线程。线程有时被称为轻量级进程。
例如:
示例 1: JVM 在单个进程中运行,并且 JVM 中的线程共享属于该进程的堆。这就是为什么多个线程可以访问同一个对象的原因。线程共享堆并拥有自己的堆栈空间。这就是一个线程对方法及其局部变量的调用如何与其他线程保持线程安全。但是堆不是线程安全的,为了线程安全必须同步。
示例 2: 程序可能无法通过读取击键来绘制图片。程序必须全神贯注于键盘输入,缺乏一次处理多个事件的能力会导致麻烦。这个问题的理想解决方案是同时无缝执行程序的两个或多个部分。线程允许我们这样做。这里画图是一个进程,读取击键是子进程(线程)。
【讨论】:
很好的答案,我喜欢它定义了它的范围(Java 世界)并提供了一些适用的示例——包括一个 (#2) 任何必须提出原始问题的人都可以立即与之相关的示例。 【参考方案14】:对于那些更喜欢通过可视化来学习的人,这是我创建的一个方便的图表来解释进程和线程。 我使用了来自 MSDN 的信息 - About Processes and Threads
【讨论】:
添加另一个进程可能会很有趣,只是为了看看多线程与多处理的比较。【参考方案15】:试图从 Linux Kernel 的 OS View 来回答这个问题
一个程序在启动到内存时就变成了一个进程。进程有自己的地址空间,这意味着在内存中有不同的段,例如用于存储编译代码的.text
段,用于存储未初始化的静态或全局变量的.bss
等。每个进程都有自己的程序计数器和用户-space 堆栈。 在内核内部,每个进程都有自己的内核栈(出于安全问题与用户空间栈分离)和一个名为task_struct
的结构,通常抽象为进程控制块,存储所有信息关于进程,例如它的优先级、状态(以及许多其他块)。 一个进程可以有多个执行线程。
来到线程,它们驻留在进程中,并与其他资源共享父进程的地址空间,这些资源可以在线程创建期间传递,例如文件系统资源、共享挂起的信号、共享数据(变量和指令),因此线程轻量级,因此允许更快的上下文切换。 在内核内部,每个线程都有自己的内核堆栈以及定义线程的task_struct
结构。因此内核将同一进程的线程视为不同的实体,并且它们本身是可调度的。同一进程中的线程共享一个称为线程组 id(tgid
) 的公共 id,也有一个称为进程 id (pid
) 的唯一 id。
【讨论】:
【参考方案16】:进程和线程都是独立的执行序列。典型的区别是(同一进程的)线程在共享内存空间中运行,而进程在不同的内存空间中运行。
过程
是一个正在执行的程序。它有文本部分,即程序代码、当前活动,由程序计数器的值和处理器寄存器的内容表示。它还包括包含临时数据(如函数参数、返回地址和局部变量)的进程堆栈,以及包含全局变量的数据段。一个进程也可能包括一个堆,它是在进程运行时动态分配的内存。
线程
线程是 CPU 利用率的基本单位;它包括线程 ID、程序计数器、寄存器集和堆栈。它与属于同一进程的其他线程共享其代码段、数据段和其他操作系统资源,例如打开的文件和信号。
-- 摘自 Galvin 的操作系统
【讨论】:
【参考方案17】:Difference between Thread and Process?
进程是应用程序的执行实例,线程是进程内的执行路径。此外,一个进程可以包含多个线程。需要注意的是,一个线程可以做任何一个进程可以做的事情。但是由于一个进程可以由多个线程组成,一个线程可以被认为是一个“轻量级”进程。因此,线程和进程之间的本质区别在于每个线程用于完成的工作。线程用于小任务,而进程用于更“重量级”的任务——基本上是应用程序的执行。
线程和进程之间的另一个区别是同一进程中的线程共享相同的地址空间,而不同的进程则不共享。这允许线程读取和写入相同的数据结构和变量,也便于线程之间的通信。进程之间的通信(也称为 IPC 或进程间通信)非常困难且占用大量资源。
这里总结一下线程和进程的区别:
线程比进程更容易创建,因为它们 不需要单独的地址空间。
多线程需要仔细编程,因为线程 共享只能由一个线程修改的数据结构 一次。与线程不同,进程不共享相同的 地址空间。
线程被认为是轻量级的,因为它们使用远 资源比进程少。
进程相互独立。线程,因为它们 共享同一个地址空间是相互依赖的,所以要小心 必须采取措施,使不同的线程不会相互踩踏。 这实际上是上述 #2 的另一种表述方式。
一个进程可以由多个线程组成。
【讨论】:
【参考方案18】:流程:
进程基本上是一个正在执行的程序。它是一个活跃的实体。 一些操作系统使用术语“任务”来指代正在执行的程序。 进程始终存储在主存储器中,也称为主存储器或随机存取存储器。 因此,进程被称为活动实体。如果机器重新启动,它就会消失。 几个进程可能与同一个程序相关联。 在多处理器系统上,可以并行执行多个进程。 在单处理器系统上,虽然没有实现真正的并行性,但应用了进程调度算法,并且处理器被调度为一次执行每个进程,从而产生并发错觉。 示例:执行“计算器”程序的多个实例。每个实例都称为一个进程。
主题:
线程是进程的子集。 它被称为“轻量级进程”,因为它类似于真正的进程,但在进程的上下文中执行并共享内核分配给进程的相同资源。 通常,一个进程只有一个控制线程——一次执行一组机器指令。 一个进程也可以由同时执行指令的多个执行线程组成。 多线程控制可以利用多处理器系统上可能的真正并行性。 在单处理器系统上,应用了线程调度算法,处理器被调度为一次运行每个线程。 在一个进程中运行的所有线程共享相同的地址空间、文件描述符、堆栈和其他与进程相关的属性。 由于进程的线程共享相同的内存,同步访问共享数据与进程变得前所未有的重要。
ref-https://practice.geeksforgeeks.org/problems/difference-between-process-and-thread
【讨论】:
一个进程的Node并发VS其他语言的多线程并行 这实际上是从 2010 年的以下答案中复制粘贴而来的……【参考方案19】:从面试官的角度来看,我想听的主要内容基本上只有 3 点,除了很明显的事情,比如一个进程可以有多个线程:
-
线程共享相同的内存空间,这意味着一个线程可以从其他线程的内存中访问内存。进程通常不能。
资源。资源(内存、句柄、套接字等)在进程终止时释放,而不是线程终止。
安全。一个进程有一个固定的安全令牌。另一方面,线程可以模拟不同的用户/令牌。
如果您想要更多,Scott Langham 的回答几乎涵盖了所有内容。 所有这些都是从操作系统的角度来看的。不同的语言可以实现不同的概念,例如任务、轻量级线程等,但它们只是使用线程(Windows 上的 Fiber)的方式。 没有硬件和软件线程。存在硬件和软件异常和中断,或者用户模式和内核线程。
【讨论】:
当你说安全令牌时,你的意思是像 Linux 上的用户凭证(用户名/密码)吗? 在windows中这是一个复杂的话题,安全令牌(实际上称为访问令牌)是一个很大的结构,包含访问检查所需的所有信息。该结构是在授权后创建的,这意味着没有用户名/密码,而是基于用户名/密码的 SID/权限列表。更多细节在这里:msdn.microsoft.com/en-us/library/windows/desktop/…【参考方案20】:-
线程在共享内存空间中运行,而进程在单独的内存空间中运行
线程是轻量级进程,而进程又是重量级进程。
线程是进程的子类型。
【讨论】:
这感觉很递归。如果扩展线程和进程之间的关系,也许会是一个更好的答案。【参考方案21】:以下是我从The Code Project 上的一篇文章中得到的。我想它清楚地解释了所有需要的东西。
线程是另一种将工作负载拆分为独立的机制 执行流。线程比进程更轻。这 意味着,它提供的灵活性低于完整的流程,但可以 启动速度更快,因为操作系统可以执行的操作更少 设置。当一个程序由两个或多个线程组成时,所有 线程共享一个内存空间。进程被赋予单独的地址空间。 所有线程共享一个堆。但是每个线程都有自己的堆栈。
【讨论】:
不确定这是否清楚,除非从已经了解线程与进程的角度来看。添加它们之间的关系可能会很有用。 不清楚。这是否意味着只有一个进程及其线程?如果有很多进程,每个进程都有很多线程怎么办?所有这些线程是否共享一个内存空间?在所有这些过程中?【参考方案22】:我已经仔细阅读了那里的几乎所有答案,唉,作为一名正在学习操作系统课程的本科生,我目前无法彻底理解这两个概念。我的意思是大多数人从一些操作系统书籍中阅读了差异,即线程能够访问事务单元中的全局变量,因为它们利用了它们的进程的地址空间。然而,新的问题出现了,为什么会有进程,众所周知,我们已经知道线程相对于进程来说是更轻量级的。下面我们通过使用one of the prior answers的图片摘录来看看下面的例子,
我们有 3 个线程同时处理一个 word 文档,例如Libre Office。如果单词拼写错误,第一个通过下划线进行拼写检查。第二个从键盘获取并打印字母。最后一个确实会在短时间内保存文档,以免在出现问题时丢失所处理的文档。 在这种情况下,3 个线程不能是 3 个进程,因为它们共享一个公共内存,即它们的进程的地址空间,因此都可以访问正在编辑的文档。 所以,道路就是这个词文档以及两台推土机,虽然其中一个在图像中没有,但它们是线程。
【讨论】:
【参考方案23】:来自嵌入式世界,我想补充一点,进程的概念只存在于具有 MMU(内存管理单元)的“大型”处理器(台式 CPU、ARM Cortex A-9)中) 以及支持使用 MMU 的操作系统(例如 Linux)。对于小型/旧处理器和微控制器以及小型 RTOS 操作系统(实时操作系统),例如 freeRTOS,没有 MMU 支持,因此没有进程,只有线程。
线程可以访问彼此的内存,并且它们由操作系统以交错方式调度,因此它们看起来是并行运行的(或者它们实际上是并行运行的多核)。
另一方面,进程存在于它们的私有虚拟内存沙箱中,由 MMU 提供和保护。这很方便,因为它启用了:
-
防止有问题的进程导致整个系统崩溃。
通过使其他进程数据不可见和保持安全性
遥不可及。
进程内部的实际工作由一个或多个线程负责。
【讨论】:
【参考方案24】:-
基本上,线程是进程的一部分,没有进程线程将无法工作。
线程是轻量级的,而进程是重量级的。
进程之间的通信需要一些时间,而线程需要更少的时间。
线程可以共享同一个内存区域,而进程却是分开的。
【讨论】:
【参考方案25】:进程:正在执行的程序称为进程
线程:线程是基于“与其他”概念与程序的其他部分一起执行的功能,因此线程是进程的一部分。..
【讨论】:
不错,尽管它引入了一个新概念(“与其他人”),对于提出问题的人来说可能是陌生的。 帖子被格式化为代码,但应该是普通文本。【参考方案26】:在使用包含多线程的 Python(解释型语言)构建算法时,我惊讶地发现,与我之前构建的顺序算法相比,执行时间并没有任何改善。为了理解这个结果的原因,我做了一些阅读,并相信我学到的东西提供了一个有趣的上下文,可以更好地理解多线程和多进程之间的区别。
多核系统可能会使用多个执行线程,因此 Python 应该支持多线程。但是 Python 不是编译语言,而是解释语言1。这意味着程序必须被解释才能运行,并且解释器在程序开始执行之前并不知道程序。然而,它所知道的是 Python 的规则,然后它会动态地应用这些规则。 Python 中的优化必须主要是解释器本身的优化,而不是要运行的代码。这与 C++ 等编译语言形成对比,并且对 Python 中的多线程有影响。具体来说,Python 使用 Global Interpreter Lock 来管理多线程。
另一方面,编译语言是经过编译的。该程序被“完全”处理,首先根据其句法定义对其进行解释,然后映射到与语言无关的中间表示,最后链接到可执行代码中。这个过程允许代码被高度优化,因为它在编译时都是可用的。各种程序交互和关系在创建可执行文件时定义,并且可以做出有关优化的稳健决策。
在现代环境中,Python 的解释器必须允许多线程,而且这必须既安全又高效。这就是解释语言与编译语言之间的区别所在。解释器不得干扰来自不同线程的内部共享数据,同时优化处理器的计算使用。
正如在之前的帖子中所指出的,进程和线程都是独立的顺序执行,主要区别在于进程的多个线程共享内存,而进程隔离它们的内存空间。
在 Python 中,全局解释器锁保护数据不被不同线程同时访问。它要求在任何 Python 程序中,任何时候都只能执行一个线程。另一方面,可以运行多个进程,因为每个进程的内存都与任何其他进程隔离,并且进程可以在多个内核上运行。
1 Donald Knuth 在《计算机编程艺术:基本算法》中对解释例程有很好的解释。
【讨论】:
【参考方案27】:目前我找到的最佳答案是Michael Kerrisk's 'The Linux Programming Interface':
在现代 UNIX 实现中,每个进程可以有多个线程 的执行。设想线程的一种方式是作为一组进程 共享相同的虚拟内存,以及一系列其他 属性。每个线程都在执行相同的程序代码并共享 相同的数据区和堆。但是,每个线程都有自己的堆栈 包含局部变量和函数调用链接信息。 [LPI 2.12]
这本书非常清晰; Julia Evans 在this article 中提到了它有助于澄清 Linux 小组的实际工作方式。
【讨论】:
这似乎直接自相矛盾。一部分说一个进程可以有多个线程。下一部分说线程是一组共享虚拟内存的进程。我不明白这两件事怎么可能是真的。 我是这样读的:把第一句话中的“拥有”这个词扔掉。就术语而言,您剩下的是 1) 单个线程和 2) 一组线程,为了方便起见,这被称为进程。这是我对 Kerrisk 的看法。 我认为他想说的是,如果您习惯于旧的 UNIX 视图,即进程是操作系统调度的,那么一组线程就像一组进程,除了它们共享一个一堆东西。 对!很好的表达方式。【参考方案28】:同一进程内的线程共享内存,但每个线程都有自己的堆栈和寄存器,线程将线程特定的数据存储在堆中。线程从不独立执行,因此与进程间通信相比,线程间通信要快得多。
进程从不共享相同的内存。当子进程创建时,它会复制父进程的内存位置。进程通信是通过使用管道、共享内存和消息解析来完成的。线程之间的上下文切换非常慢。
【讨论】:
【参考方案29】:示例 1:JVM 在单个进程中运行,并且 JVM 中的线程共享属于该进程的堆。这就是为什么多个线程可以访问同一个对象的原因。线程共享堆并拥有自己的堆栈空间。这就是一个线程对方法及其局部变量的调用如何与其他线程保持线程安全。但是堆不是线程安全的,为了线程安全必须同步。
【讨论】:
【参考方案30】:将流程视为所有权单位或任务需要哪些资源。进程可以拥有内存空间、特定输入/输出、特定文件和优先级等资源。
线程是一个可调度的执行单元,简单来说就是一系列指令的进度
【讨论】:
以上是关于进程和线程有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章