Scala Future死锁成因解析:Await.result为何引发死锁?
为什么这段Scala代码会触发死锁?
你的猜测完全正确!咱们一步步拆解这个死锁的形成过程,就能把逻辑理得明明白白:
首先看线程池的核心配置:这里用Executors.newFixedThreadPool(1)创建了仅含1个工作线程的线程池,所有Future任务的执行都依赖这唯一的线程。
接下来看具体执行流程:
- 当调用
multiply方法时,外层的Future { ... }会把它的代码块提交到这个单线程池,此时线程池的唯一线程开始执行这个multiply任务。 - 在
multiply的任务里,我们调用了addOne(x)和addOne(y),这两个方法各自生成了一个新的Future,它们会被放入线程池的任务队列中,等待空闲线程来执行。 - 随后的for推导式
result是一个组合Future,它要等a和b这两个Future都执行完成后,才能计算出最终的乘积结果。 - 最关键的一步来了:
Await.result(result, Duration.Inf)会让当前正在执行multiply任务的线程阻塞挂起,直到result完成。但此时线程池里唯一的线程正被这个阻塞的multiply任务占用着,队列里的addOne任务根本没有机会被执行——因为没有其他线程能处理它们!
这就形成了典型的循环等待死锁:
multiply的线程在等result完成,而result依赖a和b的执行结果;a和b的任务在等线程池的空闲线程,但唯一的线程被multiply的阻塞操作占着,永远不会释放。
如果把线程池的大小改成2,这个死锁就不会发生:当multiply的线程阻塞时,另一个空闲线程可以去执行addOne的任务,result就能正常完成,Await.result也能拿到结果。
内容的提问来源于stack exchange,提问作者WeiChing 林煒清
相关产品推荐
相关产品推荐

