多进程和多线程有啥区别?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多进程和多线程有啥区别?相关的知识,希望对你有一定的参考价值。
好象是一个进程里面可以包含多个线程,那具体的原理呢?
线程和进程都是现在电脑概念里比较时髦的用语,什么是多线程,什么是多进程?本文详细的给您介绍一下,希望能增进您对当代电脑技术的了解,有不到之处,还往高手予以更正。进程(英语:Process,中国大陆译作进程,台湾译作行程)是计算机中已运行程序的实体。进程本身不会运行,是线程的容器。程序本身只是指令的集合,进程才是程序(那些指令)的真正运行。若干进程有可能与同一个程序相关系,且每个进程皆可以同步(循序)或不同步(平行)的方式独立运行。进程为现今分时系统的基本运作单位线程(英语:thread,台湾译为运行绪),操作系统技术中的术语,是操作系统能够进行运算调度的最小单位。它被包涵在进程之中,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix
System
V及SunOS中也被称为轻量进程(lightweight
processes),但轻量进程更多指内核线程(kernel
thread),而把用户线程(user
thread)称为线程。
线程是独立调度和分派的基本单位。线程可以操作系统内核调度的内核线程,如Win32
线程;由用户进程自行调度的用户线程,如Linux
Portable
Thread;
或者由内核与用户进程,如Windows
7的线程,进行混合调度。
同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call
stack),自己的寄存器环境(register
context),自己的线程本地存储(thread-local
storage)。
一个进程可以有很多线程,每条线程并行执行不同的任务。
在多核或多CPU,或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见,即提高了程序的执行吞吐率。在单CPU单核的计算机上,使用多线程技术,也可以把进程中负责IO处理、人机交互而常备阻塞的部分与密集计算的部分分开来执行,编写专门的workhorse线程执行密集计算,从而提高了程序的执行效率
进程是资源分配的最小单位,线程是CPU调度的最小单位。线程和进程的区别在于,子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文.多线程主要是为了节约CPU时间,发挥利用,根据具体情况而定.
线程的运行中需要使用计算机的内存资源和CPU。
多进程:
进程是程序在计算机上的一次执行活动。当你运行一个程序,你就启动了一个进程。显然,程序是死的(静态的),进程是活的(动态的)。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是处于运行状态下的操作系统本身;所有由用户启动的进程都是用户进程。进程是操作系统进行资源分配的单位。
进程又被细化为线程,也就是一个进程下有多个能独立运行的更小的单位。在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态,这便是多任务。现代的操作系统几乎都是多任务操作系统,能够同时管理多个进程的运行。
多任务带来的好处是明显的,比如你可以边听mp3边上网,与此同时甚至可以将下载的文档打印出来,而这些任务之间丝毫不会相互干扰。那么这里就涉及到并行的问题,俗话说,一心不能二用,这对计算机也一样,原则上一个CPU只能分配给一个进程,以便运行这个进程。我们通常使用的计算机中只有一个CPU,也就是说只有一颗心,要让它一心多用,同时运行多个进程,就必须使用并发技术。实现并发技术相当复杂,最容易理解的是“时间片轮转进程调度算法”,它的思想简单介绍如下:在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短(比如10毫秒),这样用户根本感觉不出来
CPU是在轮流为多个进程服务,就好象所有的进程都在不间断地运行一样。但实际上在任何一个时间内有且仅有一个进程占有CPU。
如果一台计算机有多个CPU,情况就不同了,如果进程数小于CPU数,则不同的进程可以分配给不同的CPU来运行,这样,多个进程就是真正同时运行的,这便是并行。但如果进程数大于CPU数,则仍然需要使用并发技术。
进行CPU分配是以线程为单位的,一个进程可能由多个线程组成,这时情况更加复杂,但简单地说,有如下关系:
总线程数<=
CPU数量:并行运行
总线程数>
CPU数量:并发运行
并行运行的效率显然高于并发运行,所以在多CPU的计算机中,多任务的效率比较高。但是,如果在多CPU计算机中只运行一个进程(线程),就不能发挥多CPU的优势。
这里涉及到多任务操作系统的问题,多任务操作系统(如Windows)的基本原理是:操作系统将CPU的时间片分配给多个线程,每个线程在操作系统指定的时间片内完成(注意,这里的多个线程是分属于不同进程的).操作系统不断的从一个线程的执行切换到另一个线程的执行,如此往复,宏观上看来,就好像是多个线程在一起执行.由于这多个线程分属于不同的进程,因此在我们看来,就好像是多个进程在同时执行,这样就实现了多任务
多线程:在计算机编程中,一个基本的概念就是同时对多个任务加以控制。许多程序设计问题都要求程序能够停下手头的工作,改为处理其他一些问题,再返回主进程。可以通过多种途径达到这个目的。最开始的时候,那些掌握机器低级语言的程序员编写一些“中断服务例程”,主进程的暂停是通过硬件级的中断实现的。尽管这是一种有用的方法,但编出的程序很难移植,由此造成了另一类的代价高昂问题。中断对那些实时性很强的任务来说是很有必要的。但对于其他许多问题,只要求将问题划分进入独立运行的程序片断中,使整个程序能更迅速地响应用户的请求。
最开始,线程只是用于分配单个处理器的处理时间的一种工具。但假如操作系统本身支持多个处理器,那么每个线程都可分配给一个不同的处理器,真正进入“并行运算”状态。从程序设计语言的角度看,多线程操作最有价值的特性之一就是程序员不必关心到底使用了多少个处理器。程序在逻辑意义上被分割为数个线程;假如机器本身安装了多个处理器,那么程序会运行得更快,毋需作出任何特殊的调校。根据前面的论述,大家可能感觉线程处理非常简单。但必须注意一个问题:共享资源!如果有多个线程同时运行,而且它们试图访问相同的资源,就会遇到一个问题。举个例子来说,两个线程不能将信息同时发送给一台打印机。为解决这个问题,对那些可共享的资源来说(比如打印机),它们在使用期间必须进入锁定状态。所以一个线程可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其他线程可以接着使用同样的资源。
多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。
一个采用了多线程技术的应用程序可以更好地利用系统资源。其主要优势在于充分利用了CPU的空闲时间片,可以用尽可能少的时间来对用户的要求做出响应,使得进程的整体运行效率得到较大提高,同时增强了应用程序的灵活性。更为重要的是,由于同一进程的所有线程是共享同一内存,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。
进程间通信(IPC,Inter-Process
Communication),指至少两个进程或线程间传送数据或信号的一些技术或方法。进程是计算机系统分配资源的最小单位。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。这些进程可以运行在同一计算机上或网络连接的不同计算机上。
进程间通信技术包括消息传递、同步、共享内存和远程过程调用。 参考技术A 进程是静态的,线程是动态的,这是操作系统实现的在一块静态内存中同时运行多个程序,而每个程序又分成很多部分处理,提高效率,并行只是宏观印象,微观上一切的处理都是串行处理的(单cpu环境下)本回答被提问者采纳 参考技术B 一般运行一个程序称为一个进程。
进程可以创建线程,也可以创建进程。
线程是由进程管理的,线程之间、线程和父进程(创建线程的进程)之间可以共享内存变量(需要使用策略的)。
进程之间一般不可以直接共享内存变量,需要使用一些进程间的控制共享内存变量。
如果你使用并行计算,建议使用线程。 参考技术C 线程是CPU的处理任务,而进程是分配给程序的一个模块,相对者不同 参考技术D 这个问题我也不太明白,胡乱答几句,留下记号看高手回答.
我的理解,进程是电脑内存里加载的一些程序,线程嘛,我记得用扫描器就有开着多个线程同时运行的,这样看来线程就是同时运行的命令了吧?
异步编程和多线程有啥区别?
【中文标题】异步编程和多线程有啥区别?【英文标题】:What is the difference between asynchronous programming and multithreading?异步编程和多线程有什么区别? 【发布时间】:2016-04-13 08:50:31 【问题描述】:我认为它们基本上是一样的——编写在处理器之间分割任务的程序(在具有 2 个以上处理器的机器上)。然后我正在阅读this,上面写着:
异步方法旨在成为非阻塞操作。一个等待 异步方法中的表达式不会阻塞当前线程,而 等待的任务正在运行。相反,该表达式签署了其余部分 方法的延续并将控制权返回给调用者 异步方法。
async 和 await 关键字不会导致额外的线程 创建的。异步方法不需要多线程,因为异步 方法不在自己的线程上运行。该方法在当前运行 同步上下文并仅在线程上使用时间 方法处于活动状态。您可以使用 Task.Run 将 CPU 密集型工作移动到 后台线程,但后台线程对进程没有帮助 那只是在等待结果可用。
我想知道是否有人可以为我将其翻译成英文。它似乎区分了异步性(这是一个词吗?)和线程,并暗示您可以拥有一个具有异步任务但没有多线程的程序。
现在我了解了异步任务的概念,例如 pg 上的示例。 Jon Skeet 的 C# In Depth,第三版 467
async void DisplayWebsiteLength ( object sender, EventArgs e )
label.Text = "Fetching ...";
using ( HttpClient client = new HttpClient() )
Task<string> task = client.GetStringAsync("http://csharpindepth.com");
string text = await task;
label.Text = text.Length.ToString();
async
关键字的意思是“此函数,无论何时被调用,都不会在调用后的所有内容都需要完成的上下文中调用。” p>
换句话说,在某个任务的中间写它
int x = 5;
DisplayWebsiteLength();
double y = Math.Pow((double)x,2000.0);
,由于DisplayWebsiteLength()
与x
或y
无关,将导致DisplayWebsiteLength()
“在后台”执行,比如
processor 1 | processor 2
-------------------------------------------------------------------
int x = 5; | DisplayWebsiteLength()
double y = Math.Pow((double)x,2000.0); |
显然这是一个愚蠢的例子,但我是正确的还是我完全糊涂了还是什么?
(另外,我很困惑为什么 sender
和 e
从未在上述函数的主体中使用。)
【问题讨论】:
这是一个很好的解释:blog.stephencleary.com/2013/11/there-is-no-thread.htmlsender
和e
暗示这实际上是一个事件处理程序——几乎是唯一需要async void
的地方。最有可能的是,这会在按钮单击或类似的情况下调用 - 结果是此操作相对于应用程序的其余部分完全异步发生。但它仍然都在一个线程上 - UI 线程(在将回调发布到 UI 线程的 IOCP 线程上有一小段时间)。
Difference between Multithreading and Async program in c#的可能重复
关于DisplayWebsiteLength
代码示例的一个非常重要的说明:您不应该在using
语句中使用HttpClient
- 在重负载下,代码可能会耗尽可用套接字的数量,从而导致SocketException 错误。有关Improper Instantiation 的更多信息。
@JakubLortz 我不知道这篇文章是写给谁的。不适合初学者,因为它需要对线程、中断、CPU 相关的东西等有很好的了解。不适合高级用户,因为他们已经很清楚了。我相信它不会帮助任何人理解它的全部含义 - 抽象级别太高。
【参考方案1】:
您的误解非常普遍。很多人都被教导说多线程和异步是一回事,但事实并非如此。
类比通常会有所帮助。你在一家餐馆做饭。一份鸡蛋和烤面包的订单进来了。
同步:先煮鸡蛋,然后再煮吐司。 异步、单线程:您开始煮鸡蛋并设置计时器。你开始烤面包,并设置一个计时器。当他们都在做饭的时候,你打扫厨房。当计时器响起时,您将鸡蛋从火中取出,将吐司从烤面包机中取出并上桌。 异步、多线程:您再雇用两名厨师,一名煮鸡蛋,一名煮吐司。现在你有协调厨师的问题,以便他们在共享资源时不会在厨房中相互冲突。你必须付钱给他们。现在多线程只是一种异步是否有意义? 线程是关于工人的;异步是关于任务的。在多线程工作流中,您将任务分配给工作人员。在异步单线程工作流中,您有一个任务图,其中一些任务依赖于其他任务的结果;当每个任务完成时,它会调用代码来安排下一个可以运行的任务,给定刚刚完成的任务的结果。但是您(希望)只需要一名工人来执行所有任务,而不是每个任务一名工人。
这将有助于认识到许多任务不受处理器限制。对于处理器绑定的任务,雇用与处理器一样多的工作人员(线程)是有意义的,为每个工作人员分配一个任务,为每个工作人员分配一个处理器,并且让每个处理器只做其他工作,只计算结果为尽快。但是对于不在处理器上等待的任务,您根本不需要分配工作人员。您只需等待结果可用的消息到达,然后在等待期间执行其他操作。当该消息到达时,您可以安排已完成任务的继续,作为待办事项列表中的下一个要检查的事情。
让我们更详细地看一下 Jon 的示例。发生什么了?
有人调用 DisplayWebSiteLength。谁?我们不在乎。 它设置一个标签,创建一个客户端,并要求客户端获取一些东西。客户端返回一个对象,表示获取某物的任务。该任务正在进行中。 它是否在另一个线程上进行?可能不是。阅读Stephen's article 了解为什么没有线程。 现在我们等待任务。发生什么了?我们检查任务是否在我们创建它和等待它之间完成。如果是,那么我们获取结果并继续运行。假设它还没有完成。 我们将该方法的其余部分注册为该任务的继续并返回。 现在控制权已返回给调用者。它有什么作用?随心所欲。 现在假设任务完成。它是怎么做到的?也许它正在另一个线程上运行,或者我们刚刚返回的调用者允许它在当前线程上运行完成。无论如何,我们现在已经完成了一项任务。 已完成的任务要求正确的线程——同样,可能是only线程——来运行任务的延续。 控制权立即返回到我们刚刚在等待点离开的方法。现在有一个可用的结果,因此我们可以分配text
并运行该方法的其余部分。
就像我的比喻一样。有人向你要文件。你把文件寄出去,然后继续做其他工作。当它到达邮件时,您会收到信号,当您愿意时,您会完成其余的工作流程——打开信封,支付运费,等等。您无需雇用其他工人为您完成所有这些工作。
【讨论】:
@user5648283:硬件是考虑任务的错误级别。 任务只是一个对象,它 (1) 表示一个值将在未来变得可用,并且 (2) 当该值可用时可以运行代码(在正确的线程上)。任何单个任务将来如何获得结果都取决于它。有些人会使用“磁盘”和“网卡”等特殊硬件来做到这一点;有些会使用 CPU 等硬件。 @user5648283:再想想我的比喻。当有人要求你煮鸡蛋和烤面包时,你会使用特殊的硬件——炉子和烤面包机——你可以在硬件工作的时候打扫厨房。如果有人向您要鸡蛋、吐司和对上一部霍比特人电影的原创评论,您可以在鸡蛋和吐司正在烹饪时写评论,但您不需要为此使用硬件。 @user5648283:现在关于“重新排列代码”的问题,请考虑一下。假设你有一个方法 P,它有一个 yield return,还有一个方法 Q,它对 P 的结果进行 foreach。单步执行代码。你会看到我们运行一点点 Q 然后一点点 P 然后一点点 Q...你明白这点吗? await 本质上是化装的收益回报。现在更清楚了吗? 烤面包机是硬件。硬件不需要线程来服务它;磁盘和网卡之类的运行水平远低于操作系统线程。 @ShivprasadKoirala:这绝对不是真的。如果你相信这一点,那么你就有一些关于异步的非常错误的信念。 C# 中异步的全部意义在于它不创建线程。【参考方案2】:浏览器内 Javascript 是没有多线程的异步程序的一个很好的例子。
您不必担心多段代码同时触及同一个对象:每个函数都会在允许在页面上运行任何其他 javascript 之前完成运行。
但是,在执行 AJAX 请求之类的操作时,根本没有代码在运行,因此其他 javascript 可以响应单击事件之类的操作,直到该请求返回并调用与其关联的回调。如果 AJAX 请求返回时这些其他事件处理程序之一仍在运行,则在完成之前不会调用其处理程序。只有一个 JavaScript“线程”在运行,即使您可以有效地暂停正在执行的操作,直到获得所需信息为止。
在 C# 应用程序中,任何时候处理 UI 元素时都会发生同样的事情——只有在 UI 线程上才允许与 UI 元素交互。如果用户单击了一个按钮,而您想通过从磁盘读取一个大文件来做出响应,那么没有经验的程序员可能会在单击事件处理程序本身中读取文件,这将导致应用程序“冻结”,直到文件已完成加载,因为在释放该线程之前,不允许它响应任何更多的单击、悬停或任何其他与 UI 相关的事件。
程序员可以用来避免这个问题的一个选项是创建一个新线程来加载文件,然后告诉该线程的代码,当文件被加载时,它需要再次在 UI 线程上运行剩余的代码,以便它可以根据在文件中找到的内容更新 UI 元素。直到最近,这种方法还很流行,因为 C# 库和语言让这种方法变得简单,但从根本上说它比它必须的要复杂。
如果您考虑一下 CPU 在硬件和操作系统级别读取文件时正在做什么,它基本上是在发出一条指令,将数据从磁盘读取到内存中,然后使用读取完成时的“中断”。换句话说,从磁盘读取(或任何 I/O)本质上是一个 异步 操作。等待该 I/O 完成的线程的概念是库开发人员创建的抽象概念,以使其更易于编程。没必要。
现在,.NET 中的大多数 I/O 操作都有一个可以调用的相应 ...Async()
方法,它几乎立即返回一个 Task
。您可以向此Task
添加回调,以指定您希望在异步操作完成时运行的代码。您还可以指定您希望该代码在哪个线程上运行,并且您可以提供一个令牌,异步操作可以不时检查该令牌以查看您是否决定取消异步任务,使其有机会快速停止其工作优雅地。
在添加 async/await
关键字之前,C# 对如何调用回调代码的方式更加明显,因为这些回调采用与任务相关联的委托的形式。为了仍然为您提供使用 ...Async()
操作的好处,同时避免代码复杂性,async/await
抽象了这些委托的创建。但它们仍然存在于编译后的代码中。
因此,您可以让您的 UI 事件处理程序 await
进行 I/O 操作,释放 UI 线程来做其他事情,并在您完成读取文件后或多或少地自动返回到 UI 线程-- 无需创建新线程。
【讨论】:
只有一个 JavaScript“线程”在运行 - Web Workers 不再适用。 @oleksii:这在技术上是正确的,但我不打算深入讨论,因为 Web Workers API 本身是异步的,并且不允许 Web Workers 直接影响 javascript 值或 DOM在调用它们的网页上,这意味着该答案的关键第二段仍然成立。从程序员的角度来看,调用 Web Worker 和调用 AJAX 请求之间几乎没有区别。 浏览器内 Javascript 是没有线程的异步程序的一个很好的例子有点迂腐 - 总是至少有 1 个执行线程 @KejsiStruga:大声笑,点了。将“无线程”更改为“无多线程”以上是关于多进程和多线程有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章