java - CPU 是否会在因 IO 读/写而阻塞的 Java 线程上浪费时间?
问题描述
如果一个线程在向 IO 写入数据时被阻塞,CPU 是否需要随时给这个线程,直到这个 IO 操作完成?
如果是这样,为什么要放弃 CPU?
如果不是,除了“每个线程的堆栈”之外,还有什么东西使“每个线程的请求”在重负载下的性能不如“具有共享线程的非阻塞 IO”?
PS:我已经阅读了很多关于这个主题的 SO 问题,我找不到解决这个特定方面的答案
解决方案
如果一个线程在向 IO 写入数据时被阻塞,CPU 是否需要随时给这个线程,直到这个 IO 操作完成?
不,操作系统只会将等待再次运行的线程出列并恢复它。
如果不是,除了“每个线程的堆栈”之外,还有什么东西使“每个线程的请求”在重负载下的性能不如“具有共享线程的非阻塞 IO”?
让一个等待线程出队并恢复它对于一个线程来说可能很便宜,但是当你有数千个线程时它并不便宜。不要忘记操作系统必须计算恢复哪个线程(根据优先级),在哪里恢复它(根据可用的 CPU 和亲和性),并且 CPU 本身可能必须将线程使用的内存加载到缓存行,这是一个真正的婊子。
更不用说进入睡眠状态的线程必须将其数据从缓存行刷新到 RAM 本身,这是一项非常昂贵的操作(缓存行存在是有原因的,一个很大的原因)。
是的,数千个线程消耗的内存会占用大量内存,从而减慢整个系统的速度。
现在,并不是说 HTTP 服务器只使用线程和阻塞 IO 就不能很好地执行,但是由于今天使用异步操作(使用期货、异步/等待、回调)非常容易,我们只是更喜欢服务器的异步 IO实际上需要速度。
推荐阅读
- java - 我在从 wsdl 和 xsd 生成 java 类时遇到了这个 iisue
- python - 解压缩从 windows zip 创建的 zip 文件(发送到 -> zip)
- graphql - 你如何向不同的用户公开 GraphQL 类型的不同子集?
- postgresql - '每月的第三个星期五'到 PLPGSQL 中的时间戳?
- android - “com.google.android.packageinstaller”到底是什么
- javascript - Vue.js 计算属性来解析/格式化数据
- c++ - 如何在 C++ 的构造函数中初始化一个 cstring?
- javascript - 防止需要在 json 文件中包含键的引号?
- javascript - 如何在javascript中创建具有动态名称的变量?
- android - Android 使用 API 30 / Android R (11) 访问 android/media 文件夹