草庐IT

multithreading - 如果 goroutines 涉及用户空间线程,阻塞操作是否会导致整个线程的上下文切换?

coder 2023-06-26 原文

如果这个问题太愚蠢,我们深表歉意。我正在阅读 goroutines 的详细信息 Here .根据该页面,它说 Goroutines 被多路复用到少量操作系统线程上,而不是 1:1 映射,据我所知,我所能想到的是,有限的产生的操作系统线程数,在其中,它可能正在使用用户空间线程或协程。这个对吗?如果是这样,我可以举个例子,如果一个程序克隆了 4 个操作系统线程,其中有多个用户空间线程,并且在所有这 4 个线程中碰巧有一个阻塞操作以及非阻塞操作,操作系统会不会调度程序上下文切换所有这些线程,因为用户空间线程对操作系统线程不透明?

出于好奇,是否存在 goroutines 的可能 C 实现,这有助于理解内部结构?

最佳答案

以下是我看完之后的理解Go in Action

Goroutines 在所谓的“逻辑处理器”(不是物理处理器)中运行。这些逻辑处理器中的每一个都绑定(bind)到一个操作系统线程。

在 Go 1.5 之后,逻辑处理器的数量等于可用物理处理器的数量。

Go 调度器智能地调度多个 goroutine 在每个逻辑处理器上的运行

粗略的图表如下:-

OS Thread ------ Logical Processor ------ Goroutine 1, Goroutine 2..... Goroutine n

现在,很可能其中一个 Goroutine 进行了阻塞系统调用。发生这种情况时,

  1. 进行阻塞调用的 OS 线程和 Goroutine 是 脱离逻辑处理器

    此逻辑处理器现在没有操作系统线程。

  2. Go 调度程序创建一个新的操作系统线程,并将其附加到逻辑处理器。附加到逻辑处理器的其余 goroutine 现在继续运行。

  3. 分离的 goroutine 和它关联的操作系统线程继续阻塞,等待系统调用返回。

  4. 当系统调用返回时,goroutine 会重新附加到其中一个逻辑处理器,并放入其运行队列中。

  5. 操作系统线程“搁置以备将来使用”。我猜它被添加到某种线程池中。

如果 goroutine 进行网络 I/O 调用,则处理方式略有不同。

goroutine 与逻辑处理器分离,并移动到集成网络轮询器。一旦轮询器说 I/O 操作准备就绪,goroutine 就会重新连接到逻辑处理器来处理它。

-- 现在,回答你的问题:-)

我不是专家,但根据上述内容,我认为会发生这种情况。

由于 4 个操作系统线程中的每一个上的一个 goroutine 都进行了阻塞系统调用,因此所有 4 个线程都将与其逻辑处理器分离,并将继续阻塞直到系统调用返回。 4 个操作系统线程将与进行阻塞系统调用的相应 goroutine 相关联。

现在,这导致 4 个逻辑处理器(以及附加到它们的非阻塞 goroutines)没有任何操作系统线程。

因此,GO 调度器创建了 4 个新的 OS 线程,并将逻辑处理器分配给这些线程。

--

从操作系统的角度来看,进行阻塞调用的 4 个操作系统线程显然不能占用 CPU 时间,因为它们什么都不做。

因此它将与它选择的其他一些非阻塞线程切换它们的上下文。

关于multithreading - 如果 goroutines 涉及用户空间线程,阻塞操作是否会导致整个线程的上下文切换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39685437/

有关multithreading - 如果 goroutines 涉及用户空间线程,阻塞操作是否会导致整个线程的上下文切换?的更多相关文章

  1. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  2. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  3. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  4. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  5. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  6. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  7. ruby - 如何让Ruby捕获线程中的语法错误 - 2

    我正在尝试使用ruby​​编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?

  8. ruby - 如何在 ruby​​ 中运行后台线程? - 2

    我是ruby​​的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp

  9. ruby - 如果它是标点符号,我怎么能从字符串中删除最后一个字符,在 ruby​​ 中? - 2

    啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组

  10. ruby - Rails 开发服务器、PDFKit 和多线程 - 2

    我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它:

随机推荐