gpt4 book ai didi

scala.concurrent.blocking - 它实际上做了什么?

转载 作者:行者123 更新时间:2023-12-03 06:13:33 24 4
gpt4 key购买 nike

我花了一段时间学习 Scala 执行上下文、底层线程模型和并发性的主题。您能否解释一下scala.concurrent.blocking“调整运行时行为”“可以提高性能或避免死锁”所描述的方式在 scaladoc

the documentation ,它作为一种等待未实现 Awaitable 的 api 的方法呈现。 (也许还应该包装长时间运行的计算?)。

它实际上做了什么?

Following through the source不会轻易泄露它的 secret 。

最佳答案

阻塞旨在向ExecutionContext提示所包含的代码正在阻塞并可能导致线程饥饿。这将使线程池有机会产生新线程以防止饥饿。这就是“调整运行时行为”的含义。但这并不神奇,并且不适用于每个 ExecutionContext

考虑这个例子:

import scala.concurrent._
val ec = scala.concurrent.ExecutionContext.Implicits.global

(0 to 100) foreach { n =>
Future {
println("starting Future: " + n)
blocking { Thread.sleep(3000) }
println("ending Future: " + n)
}(ec)
}

这使用默认的全局ExecutionContext。按原样运行代码,您会注意到 100 个 Future 都立即执行,但是如果您删除 阻塞,它们一次只会执行几个。默认的 ExecutionContext 将通过生成新线程来对阻塞调用(标记为此类)使用react,因此不会因运行 Future 而过载。

现在看一下这个具有 4 个线程的固定池的示例:

import java.util.concurrent.Executors
val executorService = Executors.newFixedThreadPool(4)
val ec = ExecutionContext.fromExecutorService(executorService)

(0 to 100) foreach { n =>
Future {
println("starting Future: " + n)
blocking { Thread.sleep(3000) }
println("ending Future: " + n)
}(ec)
}

ExecutionContext 并不是为了处理生成新线程而构建的,因此即使我的阻塞代码被 blocking 包围,您也可以看到它仍然只会在一次最多 4 个 Future。这就是为什么我们说它“可以提高性能或避免死锁”——但不能保证。正如我们在后面的 ExecutionContext 中看到的,根本无法保证。

它是如何工作的?如链接所示,blocking 执行以下代码:

BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)

BlockContext.current 从当前线程检索 BlockContext,见 hereBlockContext 通常只是一个混合有 BlockContext 特征的 Thread。如源代码中所示,它要么存储在 ThreadLocal,或者如果在那里找不到它,则从当前线程中进行模式匹配。如果当前线程不是 BlockContext,则使用 DefaultBlockContext

接下来,在当前的BlockContext上调用blockOnblockOnBlockContext 中的一个抽象方法,因此它的实现取决于 ExecutionContext 如何处理它。如果我们看一下 implementation for DefaultBlockContext (当当前线程不是 BlockContext 时),我们看到 blockOn 实际上没有执行任何操作。因此,在非 BlockContext 中使用阻塞意味着根本没有做任何特殊的事情,并且代码按原样运行,没有副作用。

如果线程是 BlockContext 呢?例如,在 global 上下文中,看到 here , blockOn 做了更多的事情。深入挖掘,您可以看到它在底层使用了 ForkJoinPool,在同一代码段中定义的 DefaultThreadFactory 用于在 ForkJoinPool< 中生成新线程。/。如果没有从 BlockContext(线程)实现 blockOnForkJoinPool 不会知道您正在阻塞,也不会尝试产生更多线程作为响应。

Scala 的 Await同样,它也使用阻塞来实现。

关于scala.concurrent.blocking - 它实际上做了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29068064/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com