什么是Event Loop,计算机系统的重要概念

本文介绍了JavaScript中的EventLoop概念及其运行机制,解释了它是如何解决单线程运行带来的问题,并通过对比同步模式与异步模式,说明了EventLoop的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。

JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。

Event Loop

本文参考C. Aaron Cois的《Understanding The Node.js Event Loop》,解释什么是Event Loop,以及它与JavaScript语言的单线程模型有何关系。

想要理解Event Loop,就要从程序的运行模式讲起。运行以后的程序叫做"进程"(process),一般情况下,一个进程一次只能执行一个任务。

如果有很多任务需要执行,不外乎三种解决方法。

(1)排队。因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。

(2)新建进程。使用fork命令,为每个任务新建一个进程。

(3)新建线程。因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务。(进程和线程的详细解释,请看这里。)

以JavaScript语言为例,它是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现"假死",因为JavaScript停不下来,也就无法响应用户的行为。

你也许会问,JavaScript为什么是单线程,难道不能实现为多线程吗?

这跟历史有关系。JavaScript从诞生起就是单线程。原因大概是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API可以实现多线程,但是JavaScript本身始终是单线程的。)

如果某个任务很耗时,比如涉及很多I/O(输入/输出)操作,那么线程的运行大概是下面的样子。

synchronous mode

上图的绿色部分是程序的运行时间,红色部分是等待时间。可以看到,由于I/O操作很慢,所以这个线程的大部分运行时间都在空等I/O操作的返回结果。这种运行方式称为"同步模式"(synchronous I/O)或"堵塞模式"(blocking I/O)。

如果采用多线程,同时运行多个任务,那很可能就是下面这样。

synchronous mode

上图表明,多线程不仅占用多倍的系统资源,也闲置多倍的资源,这显然不合理。

Event Loop就是为了解决这个问题而提出的。Wikipedia这样定义:

"Event Loop是一个程序结构,用于等待和发送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)"

简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。

asynchronous mode

上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。

可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为"异步模式"(asynchronous I/O)或"非堵塞模式"(non-blocking mode)。

这正是JavaScript语言的运行方式。单线程模型虽然对JavaScript构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果部署得好,JavaScript程序是不会出现堵塞的,这就是为什么node.js平台可以用很少的资源,应付大流量访问的原因。

转至:阮一峰个人博客

<think>嗯,用户之前问了关于Ping使用的端口和服务的问题,现在又转向线程和协程的概念。他们可能刚开始学习计算机科学或者网络相关的知识,现在想进一步了解多任务处理的相关概念。 首先,我需要确定用户对操作系统和并发编程的基础了解程度。线程和协程都是并发编程中的重要概念,但层次不同。用户可能听过这些术语,但不清楚它们之间的区别和适用场景。 用户的问题比较直接,但需要结构清晰的回答。根据之前的回答,用户喜欢分点说明,所以这次也应该保持类似的格式,比如定义、区别、适用场景等。 线程是操作系统调度的基本单位,属于内核层面的概念。而协程是用户态的轻量级线程,由程序控制调度。需要解释这两者的核心区别,比如资源消耗、切换开销、并发能力等。 用户可能关心为什么需要协程,线程有什么不足。比如,线程创建和切换的开销较大,协程更轻量,适合高并发场景。可能需要举例说明,比如网络服务中处理大量连接时,协程的优势。 还要注意用户可能的实际应用场景,比如他们是否在开发高并发的服务器应用,或者进行数据处理等。这样可以帮助用户理解何时选择线程,何时使用协程。 另外,用户可能对协程的实现机制感兴趣,比如在Python中的生成器,或者Go语言的goroutine。需要简要提及不同语言中的协程实现,但避免过于深入,以免让用户感到困惑。 最后,总结两者的对比,帮助用户做出选择。确保回答真实可靠,引用正确的技术术语,同时保持语言通俗易懂,符合用户的中文理解习惯。</think>好的!以下是关于**线程**和**协程**的对比解析: --- ### **1. 线程(Thread)** - **定义** 线程是操作系统调度的最小执行单元,属于**内核级并发**机制。一个进程(如运行中的程序)可以包含多个线程,共享进程的内存空间(如堆、全局变量),但每个线程拥有独立的栈和寄存器状态。 - **特点** - **调度方式**:由操作系统内核调度(抢占式) - **资源开销**:线程创建、切换需内核介入,开销较大(典型线程栈约1MB) - **并发能力**:受限于CPU核心数,多线程并行需硬件支持 - **典型应用**:CPU密集型任务(如数值计算)、需要并行利用多核的场景 - **示例**(Python) ```python import threading def task(): print("线程执行") t = threading.Thread(target=task) t.start() ``` --- ### **2. 协程(Coroutine)** - **定义** 协程是**用户级轻量级线程**,由程序员主动控制调度,属于协作式并发。协程在单线程内通过**协作切换**实现并发,无需内核介入。 - **特点** - **调度方式**:由用户程序主动让出控制权(非抢占式) - **资源开销**:协程切换只需保存少量寄存器,内存占用通常为KB级 - **并发能力**:适合高并发I/O密集型任务(如网络请求),单线程可支撑数万协程 - **典型应用**:Web服务器、异步编程、高并发微服务 - **示例**(Python asyncio) ```python import asyncio async def task(): print("协程执行") await asyncio.sleep(1) # 主动让出控制权 asyncio.run(task()) ``` --- ### **3. 核心区别对比** | **特性** | **线程** | **协程** | |----------------|---------------------------|------------------------------| | **调度主体** | 操作系统内核 | 用户程序(开发者/运行时库) | | **切换开销** | 高(涉及内核态切换) | 极低(仅用户态操作) | | **并发规模** | 数百级别 | 数万甚至百万级别 | | **数据竞争** | 需锁/信号量避免冲突 | 单线程内无竞争(但多线程混合使用时仍需注意) | | **适用场景** | CPU密集型、多核并行 | I/O密集型、高并发请求处理 | --- ### **4. 技术演进与典型实现** - **协程实现模式** - **生成器模式**:Python的`yield`、JavaScript的`Generator` - **异步I/O框架**:Python的`asyncio`、Go的`goroutine`(严格说goroutine是更高级的抽象) - **事件循环**:Node.js的`Event Loop` - **混合使用场景** 现代高并发系统常结合两者: - 多线程处理CPU密集型任务 - 协程处理I/O密集型任务 - 例如:Nginx(多进程+协程)、Go语言(goroutine + 多线程调度器) --- ### **5. 选择建议** - **优先协程**:当需要处理大量I/O操作(如HTTP请求、数据库访问)且追求高吞吐时 - **选择线程**:当任务计算密集且需充分利用多核CPU时 - **混合架构**:使用线程池管理CPU任务 + 协程管理I/O任务(如Python的`concurrent.futures`) 理解这两者的差异,能帮助你更高效地设计并发架构!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值