You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么JavaScript阻塞函数远少于Python?asyncio及并发相关问题咨询

核心问题解答

1. 单线程阻塞的原因与requests.get的阻塞原理

你的推测完全正确:asyncio的事件循环默认跑在单线程上,一旦这个线程被阻塞,所有待调度的异步任务都会暂停执行。
requests.get这类同步库的阻塞本质是调用了操作系统的同步IO系统调用:当你发起网络请求时,操作系统会直接将当前调用线程挂起,直到网络数据返回、超时或者出错才会唤醒线程继续执行后续代码。这段挂起的时间里,线程不会响应任何其他任务,自然就卡死了整个事件循环。

2. JavaScript和Python异步生态差异的原因

这个差异完全是运行时设计导向导致的:

  • JavaScript的运行环境(浏览器、Node.js)从诞生之初就是为异步IO场景设计的,所有内置IO API(网络请求、文件读写等)都默认做了非阻塞封装:底层会把IO操作丢给内部线程池处理,完成后再通过事件队列通知主线程,上层API天然返回Promise,不需要开发者额外找专用异步库。
  • Python的标准库和大部分早期三方库都是为同步编程场景设计的,默认IO都是同步调用,没有和asyncio的事件循环做适配。要在asyncio中使用非阻塞IO,必须使用专门适配了异步事件循环的库(比如aiohttp对应requests,aiosqlite对应sqlite3),这类库底层用epoll/kqueue这类异步IO系统调用实现,等待IO的过程会主动让出线程给事件循环调度其他任务,不会造成阻塞。

3. Gogoroutines的并发机制说明

Go不存在单线程事件循环的限制,它的并发模型和前两者本质不同:

  • Go采用M:N调度模型,goroutine是Go runtime管理的用户态轻量级线程,调度权完全由Go runtime控制,不需要操作系统内核切换线程。
  • 当某个goroutine执行到阻塞IO操作(同步网络请求、休眠等)时,Go runtime会自动将这个goroutine挂起,把它占用的系统线程让给其他待执行的goroutine,等IO完成后再唤醒原goroutine继续执行。所以上层开发者不需要特意区分同步/异步库,写同步逻辑就能天然获得高并发能力。
  • Go runtime默认会利用多核CPU的多个系统线程调度goroutine,CPU密集型任务也能真正实现并行执行,不会出现单线程卡死后所有任务都暂停的问题。

内容的提问来源于stack exchange,提问作者Greg Peckory

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 21:39:04