为啥阻塞系统调用会阻塞用户级线程的整个过程?

Posted

技术标签:

【中文标题】为啥阻塞系统调用会阻塞用户级线程的整个过程?【英文标题】:Why blocking system calls blocks entire procedure with user-level threads?为什么阻塞系统调用会阻塞用户级线程的整个过程? 【发布时间】:2017-04-14 03:56:38 【问题描述】:

我不明白以下内容:

用户级线程需要非阻塞系统调用,即多线程内核。否则,整个进程都会在内核中阻塞,即使进程中还有可运行的线程。

内核线程如何处理阻塞的系统调用?在用户级线程中,当一个线程进行阻塞系统调用(例如读取)时,为什么其他线程不能继续工作?

【问题讨论】:

【参考方案1】:

在用户级线程中,当一个线程正在做一个阻塞系统时 call (e.g. read) 为什么其他线程不能继续工作?

对于用户级线程,就操作系统和内核而言,进程中只有一个线程在运行。一个线程可能正在做一些巧妙的技巧(比如从一个用户线程上下文切换到另一个),但它仍然只是一个在多个指令流之间周期性地来回切换的线程。

因此,当该单线程调用阻塞系统调用时,该单线程必须阻塞直到该系统调用返回,并且当它被阻塞时它不能做任何事情。 特别的一件事是在阻塞时不能做的是切换到另一个用户线程上下文并运行更多代码,因为没有办法调用 switch-to-the-other-用户线程上下文例程。谁会叫它?唯一可用的“真正”线程是在系统调用内部被阻塞的线程,它不能这样做,因为它在系统调用内部被阻塞。

内核线程如何处理阻塞的系统调用?

使用内核线程,内核知道进程内的所有线程,因为内核创建它们(代表应用程序)并直接管理它们,因此内核可以直接调度它们中的任何一个。因此,当线程 A 在系统调用中阻塞时,内核/调度程序可以继续运行线程 B 一段时间,因为内核知道线程 B 存在。 (与用户线程的情况相比,内核无法调度线程 B 运行,因为内核不知道线程 B 的存在;只有用户应用程序本身知道用户级线程的存在)

【讨论】:

请注意,解决此问题的方法是提供(替代?)非阻塞内核 API 函数 - 例如内核尽快返回但之后向用户空间发送某种“事情完成”通知的函数(如果线程被阻塞,则该线程将被解除阻塞)。

以上是关于为啥阻塞系统调用会阻塞用户级线程的整个过程?的主要内容,如果未能解决你的问题,请参考以下文章

深入理解并发/并行,阻塞/非阻塞,同步/异步

Mycat 网络通信模块源码

线程池

线程池

@synchronized 会阻塞整个线程吗

阻塞非阻塞同步异步