CPU会浪费时间在一个被阻塞的Java线程上进行IO读/写吗?

5

如果一个线程在向IO写入数据时被阻塞,那么CPU是否需要给这个线程任何时间,直到该IO操作完成?

如果是,为什么CPU应该放弃?

如果不是,除了"每个线程的堆栈"之外,还有什么其他因素使"每个请求一个线程"在重负载下表现不如"非阻塞IO与共享线程"?

注:我已经阅读了一定数量的SO有关此主题的问题,但我找不到回答这个特定方面的答案。

1个回答

2
如果一个线程在向IO写入数据时被阻塞,那么CPU需要给这个线程任何时间直到完成这个IO操作吗?
不需要,操作系统会将等待运行的线程出队并恢复它。
如果不是这样,除了“每个线程一个堆栈”之外,还有什么其他因素使“每个请求一个线程”在高负载下表现不如“非阻塞IO和共享线程”?
一个等待的线程出队并恢复可能对一个线程来说很便宜,但当您拥有数千个线程时,它并不便宜。不要忘记操作系统必须计算要恢复哪个线程(根据优先级),在哪里恢复它(根据可用的CPU和亲和力),CPU本身可能必须将线程使用的内存加载到缓存行中,这是真正的麻烦。
更不用说进入睡眠状态的线程必须自己将其数据刷新到RAM中,从缓存行中,这是一个非常昂贵的操作(缓存行存在有其原因)。
而且,成千上万的线程消耗的内存可能占用大量内存,从而降低整个系统的速度。
现在,并不是说HTTP服务器不能使用线程和阻塞IO表现良好,但由于今天使用异步操作(使用future、async/await和回调)非常容易,因此我们更喜欢用于实际需要速度的服务器的异步IO。

2
在异步情况下,它就像在按钮上放置一个点击监听器一样。您创建一个封装继续所需数据的对象,并且堆栈的行为与同步代码完全相同。这意味着您启动异步IO操作并返回给调用者,恢复正常的函数流程。 - David Haim
阻塞的线程将在IO控制器发出IO完成/失败的中断被CPU接收后,才会被出队并重新调度(排队)。这个说法正确吗? - Ashok Koyi
1
从编程语言的角度来看,有许多实现异步IO的方法。通常,一个程序有一个运行“事件队列”的线程 - 这是一个线程,按定义休眠,直到某个事件(完成IO、超时等)被抛出,它会醒来,出队所有相关的事件处理程序,并且自己执行它们(像node.js风格一样),或者将它们调度到线程池上(像.NET风格一样)。 - David Haim
1
哦,等等,我误解了你的问题。答案是肯定的,在同步IO中,内核从硬件(不一定是CPU)获得中断,并安排阻塞的线程执行。它取决于操作系统调度程序何时实际运行。我上面的答案是针对异步IO的。 - David Haim
1
等待的线程不等于阻塞的线程。我指的是“等待执行、CPU时间”的线程。也许“就绪线程”是一个更好的术语。 - David Haim
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接