当前位置: 首页 > 面试题库 >

Go是否会阻塞诸如Node之类的处理器密集型操作?

唐博文
2023-03-14
问题内容

Go非常适合并发,任务作为go例程传递,并且go例程在虚拟处理器中处理,每当一个go例程遇到阻塞操作(数据库调用)时,go例程便移至另一虚拟处理器在不同的线程上(通常大部分时间在另一个物理处理器上运行)…现在,我们实现了并行性。

Node.js具有类似的技术(除了所有事情都发生在同一线程上),但是将所有正在等待的虚拟进程放在等待队列中,直到它们接收到来自阻塞资源(DB,URL)的响应,然后将其发送以进行处理。

Node.js的不足之处在于它无法处理处理器密集型操作(例如循环),并且正在运行的虚拟过程将一直持续到完成而没有抢占,这就是为什么Node.js被视为明智之举尽管它具有高并发可用性,但在关键系统中使用它之前。

是的,Go产生了一个新的线程来处理阻塞的go例程,但是处理器密集型操作又如何呢?它们被视为相同,还是遭受Node问题的困扰?


问题答案:

是的,但是在实践中要比使用Node困难得多,并且从中恢复也要容易得多。节点是单线程的,除非您编写显式的多进程代码(这并不总是那么容易,特别是如果您希望具有可移植性)。Go使用N:M调度,并且具有一定数量的正在运行的最大线程数(默认情况下等于逻辑CPU的数量,但是可调)。注意
running :等待阻塞操作的goroutine被“冻结”,不算在占用正在运行的线程中。

因此,如果您有一个goroutine进行CPU密集型工作,那么通常不会影响其他goroutine的运行能力,因为还有很多其他线程可以运行它们。如果您
所有 的goroutine都被计算所占据,那么其他程序确实没有机会运行,直到有人放弃了CPU。如果您实际上正在完成工作,那么这可能 不一定
会成为问题,因为您的所有CPU都在进行实际工作,但是当然有时可能在对延迟敏感的情况下。

如果有问题,可以想到三种解决方案

  1. runtime.Gosched在长时间计算期间使用,可以控制处理器,从而使其他goroutine可以运行。无需进行其他任何更改;这只是与合作调度程序一起工作的一种方式。Gosched可能会立即返回,也可能稍后返回。

  2. 使用工作池将并行的CPU密集型工作量限制为少于GOMAXPROCS。Go使这变得非常容易。

  3. 同一枚硬币的另一面:将GOMAXPROCS提升到并行计算任务的预期数量以上。这可能是最糟糕的主意,并且至少会在一定程度上影响调度,但是它仍然可以正常工作,并确保您有可用于处理事件的线程。



 类似资料:
  • ReplyingKafkaTemplate是否阻塞?有无反应性替代方案?

  • 我刚从Vert开始。并且想了解在处理REST HttpRequest时,处理潜在长(阻塞)操作的正确方法是什么。该应用程序本身就是一个Spring应用程序。 到目前为止,我有一个简化的REST服务: Spring配置: 现在的问题是:如何正确处理(阻止)调用我的postgresService,这可能需要更长的时间,如果有很多项目得到/返回? 在研究和查看一些示例后,我看到了一些方法,但我不完全理解

  • OpenResty 的诞生,一直对外宣传是同步非阻塞(100% non-blocking)的。基于事件通知的 Nginx 给我们带来了足够强悍的高并发支持,但是也对我们的编码有特殊要求。这个特殊要求就是我们的代码,也必须是非阻塞的。如果你的服务端编程生涯一开始就是从异步框架开始的,恭喜你了。但如果你的编程生涯是从同步框架过来的,而且又是刚刚开始深入了解异步框架,那你就要小心了。 Nginx 为了减

  • 我理解了Node是如何使用操作系统的去多路复用器使非阻塞调用异步的,它通过避免创建一百万个线程(每个客户端一个线程)来节省大量的内存成本,从而在单个线程中处理所有请求。它还帮助开发人员在更简单的应用程序中处理并发问题way.All目前为止做得很好。 当线程池进入节点留档时,我的麻烦就开始了picture.its在节点留档中,只要操作系统的多路分解器支持不好,节点就使用线程池(默认为4个线程,最大1

  • 问题内容: 我正在通过TCP / IP套接字读取数据流。流负载非常不均匀。有时每秒会有大量数据到达,有时一个小时没有数据到达。在长时间不活动的情况下(远程服务器没有数据,但连接仍然在线),我的程序应采取一些措施。 我正在使用select()实现超时。它告诉我是否已经准备好数据,但是我不知道在不引起read()阻塞的情况下我可以读取多少数据。阻止是无法接受的,因为它的持续时间可能远远超过我需要的超时

  • 这一节解释 BlockingObservable 的子类. 一个阻塞的Observable 继承普通的Observable类,增加了一些可用于阻塞Observable发射的数据的操作符。 要将普通的Observable 转换为 BlockingObservable,可以使用 Observable.toBlocking( )) 方法或者BlockingObservable.from( )) 方法。