2

我们有一个由我们正在积极开发的 fortran 二进制文件支持的 java 应用程序。我主要在 java 方面,我认为我的工作是保护在 fortran 上工作的人免受一些可能会打扰他们的讨厌的系统事情的影响,比如并发性,而不是强迫他们公开复杂的 API。

我按照这些思路做出的一个决定是将 Java 中的 JNA 样式回调传递到我们的 fortran 二进制文件中。当这个回调被执行时,我们的调用栈看起来像这样:

UIframework.click.java -- com.sun#1234
OurCode.UIHandlers.java -- our.code#2345
OurCode.doHeavyComputation.java -- our.code#4567
JNASurrogates.java -- com.sun.jna#456
JNASurrogates.proxy.f99 -- com.sun.proxies
HeavyComputation.f99 -- /code/algorithm.f99#1234
JNASurrogates.executeCallback.proxy.f99 -- com.sun.proxies
JNASurrogates.java -- com.sun.jna#1234
OurCode.computationComponents.java -- our.code#6789
//bottom of callstack

我的问题是线程之一:如何处理对同一个内存中 fortran DLL 的两个线程访问?我的问题植根于如何在内存中处理调用堆栈的确切细节:为了让 fortran 编译器生成可以从 JNA 调用的代码,而无需一个程序计数器破坏另一个,该编译器必须具有某种与 JVM 就调用堆栈的存储位置达成共识。X86 是否为我们提供了某种单独的程序计数器容器Pthreadsjava.lang.Thread, 和其他线程库都利用这些容器,允许安全隔离调用堆栈?


为了让事情变得真正有趣,我也在讨论使用Quasar —— 对于那些不熟悉的人,Quasar 提供了所谓的“纤维”,它们是“轻量级线程”,由堆栈协同程序实现,这意味着 Quasar 执行堆栈的直接操作-帧。

问题是,虽然我在概念上很乐意将 公开OurCode.computationComponents为回调,但一些业务需求决定了我不能。与其要求我们杰出的 fortran 程序员将他们现有的代码转换为具有显式入口和出口(返回)点的东西,我更愿意使用协程来利用我们现有的代码。

这个想法是协同例程将产生OurCode.computationComponents.java任何作为返回值传递给computationComponents. 然后调用者将完成计算组件回调通常所做的工作,将结果从 with 传入,这将返回并最终返回到HeavyComputation.f99doHeavyComputationresumeHeavyComputationcomputationComponentsHeavyComputation.f99

我当然可以使用阻塞队列和多线程来完成所有这些工作,但试图限制自己使用一个线程意味着我对 Quasar 有一些了解,这有几个原因。

Quasar 能否处理并安全地恢复与我们正在使用的堆栈一样复杂的堆栈?

4

1 回答 1

1

操作系统提供线程。如果其他编程模型(Java、Quasar 等)在用户空间中,则必须在此基础上构建它们。您的 Quasar“轻量级线程”仍将存在于您的操作系统进程和操作系统线程的上下文中。由于您的操作系统线程可以共享内存,因此您的“轻量级线程”也可以。从不同的“轻量级线程”通过 JNA 对 Java 的回调似乎都在同一个 Java 映射线程中(因此是同一个本机线程)。

无论 Quasar 为其协程进行的运行时堆栈如何洗牌,对 Java 端来说都是不透明的。

于 2016-09-29T13:09:10.810 回答