gpt4 book ai didi

java - JPL 库在多线程程序中的意外行为(Java 和 Prolog 的接口(interface))

转载 作者:行者123 更新时间:2023-12-01 05:05:16 26 4
gpt4 key购买 nike

我一直在尝试 JPL 的多线程功能。据我从源代码中的注释中了解到,每个 Java 线程都分配了一个不同的 Prolog 引擎。显然,当在线程 A 中启动一个查询,在线程 B(由线程 A 生成)中执行另一个查询,并在线程 A 中再次执行第三个查询时,就会出现问题。

以下代码片段说明了该问题:

public static void main(String[] args) {
try {
...
Query query;
query = new Query("true");
System.out.println(query.hasSolution()); //succeeds

Thread t = new Thread() {
@Override
public void run() {
Query query2 = new Query("true");
System.out.println(query2.hasSolution()); //succeeds
}
};
t.start();
t.join();

query = new Query("true");
System.out.println(query.hasSolution()); //fatal error
} catch (Exception e) {
throw new RuntimeException(e);
}
}

由于 JPL 文档提到不能同时激活两个查询,因此代码会等到线程完成后再继续执行最后一个查询(我尚不清楚该约束是否仅适用于以下查询)同一线程或者如果它适用于不同线程和引擎中的查询)。

在前面的示例中,只有前两个查询成功。当执行第三个查询时,我收到此 fatal error :

#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x000000010db65bd5, pid=79191, tid=7171
#
# JRE version: 7.0_06-b24
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.2-b09 mixed mode bsd-amd64 compressed oops)
# Problematic frame:
# C [libYap.dylib+0x125bd5] PL_open_foreign_frame+0x45
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
...

这是 JPL 中的错误吗?在这种情况下,有人知道使用 JPL 进行多线程处理的解决方法吗?

我已经使用 YAP 版本 6.2.2 和 6.3.2 进行了测试,结果相同。

更新:

正如 @sharky 所建议的,显然这是 YAP 二进制文件(或 YAP 的 JPL 端口)的问题。使用 SWI 时,问题中显示的示例工作正常。

我仍然对多线程程序中的 JPL 行为感到困惑。查看 JPL 库中 Query 类中 open 方法的源代码和注释:

public synchronized final void open() {
...
if (Prolog.thread_self() == -1) { // this Java thread has no attached Prolog engine?
engine = Prolog.attach_pool_engine(); // may block for a while, or fail
} else { // this Java thread has an attached engine
engine = Prolog.current_engine();
}
...
}

似乎是说 JPL 将为每个线程创建一个新的逻辑引擎。但是,如果我执行这个简单的程序:

Thread t = new Thread() {
@Override
public void run() {
Query query = new Query("assert(x)");
query.hasSolution()
query = new Query("x");
System.out.println("Thread1 x:" + query.hasSolution()); //query succeeds
}
};
t.start();
t.join();

t = new Thread() {
@Override
public void run() {
Query query = new Query("x");
System.out.println("Thread2 x:" + query.hasSolution()); //query also succeeds
}
};
t.start();
t.join();

我可以看到以下输出:

Thread1 x:true
Thread2 x:true

显然,第二个线程正在访问与第一个线程相同的 Prolog 引擎,而不是源代码及其注释似乎暗示的新引擎。

如果有人有 JPL 和多线程经验,请澄清这一点。

最佳答案

现在我找到了可能的解决方案(但是有一种方法仍然可以访问定义的子句)

你可以使用模块!序言文件:

:-module(thread1,[]).
x.

然后在thread1中你可以询问thread1:x并且它会成功并且thread2将启动一个异常(你可以捕获它并说失败...)(除非你没有定义x动态)

另一种方法是使用 thread_local...但你必须将每个子句定义为 thread_local(无聊!)

关于java - JPL 库在多线程程序中的意外行为(Java 和 Prolog 的接口(interface)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12803898/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com