我一直在尝试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文档提到同时没有两个查询可以处于活动状态,因此代码会等到线程完成后再继续执行上一个查询(如果该约束仅适用于查询,则我还不清楚相同的线程或它是否适用于不同线程和引擎中的查询。)
在前面的示例中,只有前两个查询成功。执行第三个查询时,我得到了这个致命的错误:
#
# 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库中查看open
类中Query
方法的源代码和注释:
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和多线程的经验,请澄清一下。
答案 0 :(得分:0)
现在我找到了可能的解决方案(但是仍有一种方法可以在定义的条款中访问)
您可以使用模块! prolog文件:
:-module(thread1,[]).
x.
然后在thread1中你可以问thread1:x
它会成功
和thread2将启动一个异常(你可以捕获它并说失败......)(除非你没有定义x动态)
另一种方法是使用thread_local ......但你必须将每个子句定义为thread_local(无聊!)