Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 这种僵局在Scala未来是如何发生的?_Multithreading_Scala_Asynchronous_Future - Fatal编程技术网

Multithreading 这种僵局在Scala未来是如何发生的?

Multithreading 这种僵局在Scala未来是如何发生的?,multithreading,scala,asynchronous,future,Multithreading,Scala,Asynchronous,Future,这段代码摘录自。 这是一个如何在Scala中进入死锁的示例 import java.util.concurrent.Executors import scala.concurrent._ implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1)) def addOne(x: Int) = Future(x + 1) def multiply(x: Int, y: Int) = Future

这段代码摘录自。 这是一个如何在Scala中进入死锁的示例

import java.util.concurrent.Executors
import scala.concurrent._
implicit val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))

def addOne(x: Int) = Future(x + 1)

def multiply(x: Int, y: Int) = Future {
  val a = addOne(x)
  val b = addOne(y)
  val result = for (r1 <- a; r2 <- b) yield r1 * r2

  // This can dead-lock due to the limited size of our thread-pool!
  Await.result(result, Duration.Inf)
}
我理解代码的作用,但不了解它是如何执行的

为什么是行wait.resultresult,Duration.Inf导致死锁?是的,我测试过了

乘法函数的最外层未来不是占用了所有线程池(单个线程池)并因此死锁,因为addOne未来永远被阻塞在等待线程上吗

Await.result(result, Duration.Inf)
当您使用wait时,您正在等待将来完成。你给了我无限的时间。所以,不管怎样,如果未来永远无法完成,主线程将无限等待

当您使用wait时,您正在等待将来完成。你给了我无限的时间。所以,不管怎样,如果未来永远无法完成,主线程将进入无限等待。

首先,我想说,这段代码可以模拟死锁,但不能保证它总是处于死锁中。 上面的代码中发生了什么。线程池中只有一个线程。一旦我们调用多线程函数,因为它是未来的,所以它应该在一个单独的线程上运行,比如说我们将线程池中的单个线程分配给这个函数。 现在函数addOne也是一个未来,因此它将再次开始在同一线程上运行,但不会等待a=addOne完成并移动到下一行b=addOne,因此执行a=addOne的同一线程现在执行b=addOne,所有的值将永远不会计算,未来也不会完成,因为我们只有一个线程,与b=addOne行相同的情况下,它的控件将不会等待完成该未来,并移动到for循环,因为它在Scala中也是异步的,因此它将再次不求值并移动到最后一行wait,它将等待无限长的时间来完成前一个未来

进入死锁的充分必要条件

互斥条件 等待状态 无先发制人条件 循环等待条件 这里我们可以看到,我们只有一个线程,因此要执行的进程不是互斥的

一旦线程正在执行特定的块,因此它是一个未来,而不是等待完成它,它将继续执行下一个块,因此它将到达WAIT语句,线程将保持在那里,而所有其他未完成的未来都在等待线程完成未来

一旦线程被分配给wait,它就不能被抢占,这就是为什么我们不能执行剩余的未完成的未来

循环等待是存在的,因为等待是等待非完整的未来完成,而其他期货则等待等待呼叫完成

简单地说,我们可以说控制将直接到达等待语句,并开始等待非完整期货完成,而这无论如何都不会发生。因为我们的线程池中只有一个线程

首先,我想说这段代码可以模拟死锁,但不能保证它总是处于死锁状态。 上面的代码中发生了什么。线程池中只有一个线程。一旦我们调用多线程函数,因为它是未来的,所以它应该在一个单独的线程上运行,比如说我们将线程池中的单个线程分配给这个函数。 现在函数addOne也是一个未来,因此它将再次开始在同一线程上运行,但不会等待a=addOne完成并移动到下一行b=addOne,因此执行a=addOne的同一线程现在执行b=addOne,所有的值将永远不会计算,未来也不会完成,因为我们只有一个线程,与b=addOne行相同的情况下,它的控件将不会等待完成该未来,并移动到for循环,因为它在Scala中也是异步的,因此它将再次不求值并移动到最后一行wait,它将等待无限长的时间来完成前一个未来

进入死锁的充分必要条件

互斥条件 等待状态 无先发制人条件 循环等待条件 这里我们可以看到,我们只有一个线程,因此要执行的进程不是互斥的

一旦线程正在执行特定的块,因此它是一个未来,而不是等待完成它,它将继续执行下一个块,因此它将到达WAIT语句,线程将保持在那里,而所有其他未完成的未来都在等待线程完成未来

一旦线程被分配给wait,它就不能被抢占,这就是为什么我们不能执行剩余的未完成的未来

和c 循环等待是存在的,因为等待是等待非完整的未来完成,而其他期货则等待等待呼叫完成

简单地说,我们可以说控制将直接到达等待语句,并开始等待非完整期货完成,而这无论如何都不会发生。因为我们的线程池中只有一个线程

乘法函数的最外层未来不是占用了所有线程池(单个线程池)并因此死锁,因为addOne未来永远被阻塞在等待线程上吗

是的,有点

当您调用val a=addOnex时,您将创建一个新的未来,开始等待线程。但是,正如您所注意到的,唯一的线程当前正在由最外层的将来使用。如果没有等待,这将不会是一个问题,因为期货能够处理这种情况。但是,这一行:

Await.result(result, Duration.Inf)
导致外部未来等待结果未来,该结果未来无法运行,因为外部未来仍在使用唯一可用的线程。当然,它也不能运行,因为a和b期货不能运行,同样是由于外部期货

下面是一个简单的例子,它也可以在不创造太多未来的情况下实现死锁:

def addTwo(x: Int) = Future {
  Await.result(addOne(x + 1), Duration.Inf)
}
乘法函数的最外层未来不是占用了所有线程池(单个线程池)并因此死锁,因为addOne未来永远被阻塞在等待线程上吗

是的,有点

当您调用val a=addOnex时,您将创建一个新的未来,开始等待线程。但是,正如您所注意到的,唯一的线程当前正在由最外层的将来使用。如果没有等待,这将不会是一个问题,因为期货能够处理这种情况。但是,这一行:

Await.result(result, Duration.Inf)
导致外部未来等待结果未来,该结果未来无法运行,因为外部未来仍在使用唯一可用的线程。当然,它也不能运行,因为a和b期货不能运行,同样是由于外部期货

下面是一个简单的例子,它也可以在不创造太多未来的情况下实现死锁:

def addTwo(x: Int) = Future {
  Await.result(addOne(x + 1), Duration.Inf)
}

为什么def addTwox:Int=Future{addOnex+1}有效?res5:Future[Future[Int]=FutureSuccesFutureSuccess3,它有两个FutureSuccess,它应该已经耗尽了所有线程。@WeiChingLin,因为你没有通过wait.result要求它提供另一个线程的结果,所以它不需要同时计算这两个线程。为什么def addTwox:Int=Future{addOnex+1}有效?res5:Future[Future[Int]=futuresuccesfuturesuccess3,它有两个futuresuccess,它应该已经耗尽了所有线程。@WeiChingLin,因为您没有通过wait.result要求它提供另一个线程的结果,所以它不需要同时评估这两个线程。