当前位置: 首页 > 知识库问答 >
问题:

Java Fork/Join关于堆栈使用的说明

章威
2023-03-14

我阅读了Java 7中引入的Fork/Join框架的实现,我只是想检查一下我是否理解这种魔力是如何工作的。

据我所知,当一个线程分叉时,它会在其队列中创建子任务(其他线程可能会也可能不会窃取)。当线程尝试“加入”时,它实际上会检查其队列中的现有任务,然后递归地执行这些任务,这意味着对于任何“加入”操作,将向线程调用堆栈中添加2个帧(一个用于加入,另一个用于新执行的任务调用)。

据我所知,JVM不支持尾部调用优化(在这种情况下,这可能有助于删除join方法堆栈框架),我相信,当执行一个包含许多forks和join的复杂操作时,一个线程可能会抛出< code>StackOverflowError。

我说得对吗?还是他们找到了一些很酷的方法来阻止它?

编辑

这里有一个场景可以帮助澄清这个问题:假设(为了简单起见)我们在forkjoin池中只有一个线程。在某个时间点——线程分叉,然后调用join。而在join方法中,线程发现它可以执行分叉任务(正如它在队列中发现的那样),因此它调用下一个任务。这个任务依次分叉,然后调用join——因此在执行join方法时,线程将在它的队列中找到分叉的任务(像以前一样)并调用它。在这个阶段,调用堆栈将至少包含两个连接和两个任务的帧。

正如您所看到的,fork连接框架已转换为纯递归。因为java不支持尾部调用优化-如果深入足够深,java中的每个递归都可能导致StackOverflow Error

我的问题是 - 分叉/连接框架的实现者是否找到了一些很酷的方法来防止这种情况。

共有3个答案

孙洋
2023-03-14

我希望我以正确的方式理解你。

forkjoinpool中有一个内部队列,用于保存您要执行的任务,因此不会引发堆栈溢出,但您必须为高内存利用率做好准备。

fork方法非常有趣的地方ForkJoinWorkerThread.pushTask不安全的对象使用,所以你应该注意数组是用来存储任务的。

编辑:首先,很简单 - 当您处于队列的顶部时,您只需取消推送并执行,然后返回retult。(叉突.java:353)

当存在依赖关系时,使用不同的方法,在这种情况下,控制返回到WorkerThread,后者负责检测链并执行它们。由第一个工作者检查本地队列中是否有任何未完成的任务,如果没有这样的任务,它就执行传递的作业并返回结果,否则就进入下一个情况。这是帮助偷窃者好几次。什么也帮不上忙...在第一步等于MAX_HELP的retries现在为零——控制被传递给池,池执行几个检查并执行tryAwaitDone。在这个方法中,调用wait来等待任务完成。

这意味着fork-join池将在几个步骤中完成,通过避免调用等待来优化速度和时间。然而,它可能会在等待中完成,然后这将意味着启动同步过程,这是非常昂贵的。

所以没有无限深度的后续连接,而是尽可能快地执行任务的逻辑尝试。

白吕恭
2023-03-14

一般来说,每个压入堆栈的新任务都是前一个任务的一半大小。所以工作量随着栈的大小成指数增长。即使只有很少的一堆,你也能完成足够多的工作,让你忙上一段时间。

须峰
2023-03-14

不幸的是,在线程递归堆栈方面没有什么神奇的事情发生。如果您的初始任务分叉/拆分,并且没有合理的解析点,那么您将遇到StackOverflowers错误。

您可能可以理解为什么 JavaDoc 上的教程将每个子任务分成两半。

 类似资料:
  • 6.1.3 堆栈段的说明 堆栈段是一个特殊的段,在程序中可以定义它,也可以不定义。除了要生成COM型执行文件的源程序外,一个完整的源程序一般最好定义堆栈段。如果在程序中不定义堆栈段,那么,操作系统在装入该执行程序时将自动为其指定一个64K字节的堆栈段。 在程序没有定义堆栈段的情况下,在由连接程序生成执行文件时,将会产生一条如下的警告信息,但程序员可以不理会它,所生成的执行文件是可以正常运行的。 w

  • 本文向大家介绍说一下堆栈的区别?相关面试题,主要包含被问及说一下堆栈的区别?时的应答技巧和注意事项,需要的朋友参考一下 功能方面:堆是用来存放对象的,栈是用来执行程序的。 共享性:堆是线程共享的,栈是线程私有的。 空间大小:堆大小远远大于栈。

  • 本文向大家介绍 请你说一说堆和栈的区别?相关面试题,主要包含被问及 请你说一说堆和栈的区别?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其 操作方式类似于数据结构中的栈。 堆区(heap)— 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。它与数据结构中的堆是两回事,分配方式类似于链表。 区别

  • 本文向大家介绍请你说一说堆和栈的区别?相关面试题,主要包含被问及请你说一说堆和栈的区别?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 堆栈空间分配区别: 1、栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈; 2、堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。 二、堆栈缓存方

  • 本文向大家介绍关于laravel 子查询 & join的使用,包括了关于laravel 子查询 & join的使用的使用技巧和注意事项,需要的朋友参考一下 本项目中关联了2个数据库 在某个需求中,需要使用子查询获取snapshot快照表库的关联数据,从而实现以下sql逻辑 其中子查询主要用到以下query builder语句 而join语句中可传入匿名函数重新构造,如再其中加多几个连接条件,或者查

  • 我有vframe函数并生成了如下的汇编代码 如果我们看到从8到11行,我们没有在堆栈上推送p的地址,但汇编已经假设 如果我们希望某些参数不被破坏,我们会推送一些寄存器并将被调用者保存的寄存器移动到推送的寄存器。但是,在这种情况下,似乎不是。关于局部变量还有其他约定吗,比如i和