首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解关于取消的cats.effect.Concurrent

理解关于取消的cats.effect.Concurrent
EN

Stack Overflow用户
提问于 2020-05-24 03:17:05
回答 1查看 568关注 0票数 4

给予:

build.sbt

代码语言:javascript
复制
scalaVersion := "2.13.2"
libraryDependencies += "org.typelevel" %% "cats-effect" % "2.1.3"

src/main/scala/net/Main.scala

代码语言:javascript
复制
package net

import cats.effect._
import cats.implicits._
import java.util.concurrent.TimeUnit
import scala.concurrent.duration._

object App extends IOApp { self: IOApp =>
  override def run(args: List[String]): IO[ExitCode] =
    for {
      _ <- uncancellable
      _ <- notUncancellable
    } yield ExitCode.Success

  private def uncancellable: IO[Unit] = {
    val tick: IO[Unit] = Concurrent[IO].uncancelable(self.timer.sleep(10.seconds))

    for {
      _ <- IO(println("uncancellable"))
      fiber <- Concurrent[IO].start(tick)
      _ <- IO(println("seconds begin: " + FiniteDuration.apply(System.nanoTime(), TimeUnit.NANOSECONDS).toSeconds))
      _ <- fiber.cancel
      _ <- fiber.join
      _ <- IO(println("seconds done : " + FiniteDuration.apply(System.nanoTime(), TimeUnit.NANOSECONDS).toSeconds))
    } yield ()
  }

  private def notUncancellable: IO[Unit] = {
    val tick: IO[Unit] = self.timer.sleep(10.seconds)

    for {
      _ <- IO(println("notUncancellable"))
      fiber <- Concurrent[IO].start(tick)
      _ <- IO(println("seconds begin: " + FiniteDuration.apply(System.nanoTime(), TimeUnit.NANOSECONDS).toSeconds))
      _ <- fiber.cancel
      _ <- fiber.join
      _ <- IO(println("seconds done : " + FiniteDuration.apply(System.nanoTime(), TimeUnit.NANOSECONDS).toSeconds))
    } yield ()
  }
}

运行它将显示以下输出:

代码语言:javascript
复制
sbt:cats-effect-cancellation-question> run
[info] Compiling 1 Scala source to /Users/kevinmeredith/Workspace/cats-effect-cancellation-questions/target/scala-2.13/classes ...
[info] Done compiling.
[info] Packaging /Users/kevinmeredith/Workspace/cats-effect-cancellation-questions/target/scala-2.13/cats-effect-cancellation-question_2.13-0.1.jar ...
[info] Done packaging.
[info] Running net.App 
uncancellable
seconds begin: 303045
seconds done : 303055
notUncancellable
seconds begin: 303055
^C$

请注意,30秒后,我取消了它。

为什么"seconds done :不打印:

代码语言:javascript
复制
notUncancellable
seconds begin: 303055
^C$
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-24 19:47:23

我相信uncancellable是不言自明的。

在不可接受的情况下,您有类似于这个GitHub问题的情况。

正如Alexandru Nedelcu所说:

fiber.cancel使fiber.join在IO情况下是不终止的.因此,fiber.join永远不会完成,而且这种保证永远不会得到评估的机会。 如果你也取消了,你也可以强制做一个评估,如果你关心那个fiber.join的结果,你需要在一个真正的应用程序中这样做。

据我所知,这可能是对合同的解释

代码语言:javascript
复制
  /**
   * Returns a new task that will await for the completion of the
   * underlying fiber, (asynchronously) blocking the current run-loop
   * until that result is available.
   */
  def join: F[A]

取消的光纤不能返回成功的价值-这是显而易见的。但如果它又失败了.它还将返回一个值,该值可以被认为是由光纤计算的值--它不应该返回任何值,因为它被取消了!

因此,在这种情况下,整个线程都在等待一个从未到达的值。

为了避免这样的陷阱,您可以使用一些不太“低层次”的东西,比如racePair或类似的东西,这样可以避免自己处理这些问题。您可以阅读Oleg关于纤维安全的短文。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61981204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档