我一直在試驗JPL的多線程功能。就我所瞭解的源代碼中的註釋而言,每個Java線程都分配了一個不同的Prolog引擎。 顯然有當查詢在線程A開始的問題,另一個查詢在線程B(由線程A生成)執行,以及第三查詢在線程A再次執行多線程程序中的JPL庫的意外行爲(接口Java和Prolog)
下面的代碼片斷示出問題:
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進行了測試,結果相同。
UPDATE:
作爲@sharky建議的,顯然它與YAP二進制文件中的問題(或JPL端口YAP)。在使用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和多線程的經驗請澄清這一點。
這是一個問題或JPL一個錯誤報告? –
Hi @Daniel,剛剛在最後添加了一行額外的說明 – Sergio
您是否嘗試過使用SWI作爲後端來查看問題出在YAP二進制文件中? – sharky