当前位置: 首页 > 知识库问答 >
问题:

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

尉迟高澹
2023-03-14

我不明白以下几点:

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

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

共有1个答案

赫连正初
2023-03-14

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

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

因此,当该单线程调用阻塞系统调用时,该单线程必须阻塞,直到该系统调用返回,而当它被阻塞时,它不能做任何事情。在阻塞时,它尤其不能做的一件事是切换到另一个用户线程上下文并运行更多的代码,因为无法调用切换到另一个用户线程上下文例程。谁会叫它?唯一可用的“真正”线程是在系统调用中被阻塞的线程,而它不能这样做,因为它在系统调用中被阻塞了。

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

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

 类似资料:
  • 我完全混淆了,,。 哪个是阻塞,哪个不是? 我的意思是如果我使用父进程是否等待子进程返回/才继续执行。 如何影响这些调用?

  • 在上一节中,我们看到了 take Effect 让我们可以在一个集中的地方更好地去描述一个非常规的流程。 重温一下登录流程示例: function* loginFlow() { while(true) { yield take('LOGIN') // ... perform the login logic yield take('LOGOUT') // ...

  • 问题内容: 当用户选择在另一个线程中启动阻止进程的菜单项时,我试图在JavaFX 8应用程序中提供反馈。在我的实际应用程序中,它是文件下载,但是通过示例,我使用最少的代码创建了一个测试用例: 它的工作方式如下:当选择“开始”菜单项时,主菜单文本应立即更改为“正在运行…”,然后应附加“完成!”。经过5秒钟的模拟我的文件下载的睡眠。 实际上发生的是,即使我正在使用,在阻止过程完成 后 , 两个 文本更

  • 线程实例的join()方法可用于将一个线程的执行开始“连接”到另一个线程的执行结束,这样一个线程在另一个线程结束之前不会开始运行。如果对线程实例调用join(),则当前运行的线程将阻塞,直到线程实例完成执行 但是如果我有多个线程并且当我在循环内部调用join时。所有线程并行运行。但是根据连接的概念,首先连接的线程应该完成,然后只有主线程才允许连接其他线程。 } 在上面的代码中,如果第一个线程被连接

  • 我不明白为什么webclient会阻止我使用gradle的主要netty线程,以下是它的依赖项: 这个gradle脚本在两个应用程序中都使用。在第一个应用程序中,我执行: 第二个应用程序模拟长响应处理: 我希望呼叫服务不会阻塞主线程,而是会继续处理传入的连接,但直到我收到第一个呼叫的响应(睡眠将起作用),我的下一个连接将挂起等待。 结果:第一个应用程序像tomcat一样工作,只有一个线程 我的问题

  • 问题内容: 注意:这不是有关settimeout的复制文章,此处的关键答案是浏览器设计选项。 我开始研究node.js:一个测试异步的简单示例: 一件有趣的事情是,在带有curl的lind命令和浏览器中,它的行为是不同的:在Ubuntu 12.10中,我在两个控制台中使用curl localhost:8080,它们在几乎相同的10个发送中进行响应。 但是,我打开了两个浏览器,几乎同时发出了请求,但