2012-10-09 26 views
1

我一直在試驗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和多線程的經驗請澄清這一點。

+0

這是一個問題或JPL一個錯誤報告? –

+0

Hi @Daniel,剛剛在最後添加了一行額外的說明 – Sergio

+1

您是否嘗試過使用SWI作爲後端來查看問題出在YAP二進制文件中? – sharky

回答

0

現在我已經找到了可行的解決方案(但有一種方法,在規定的條款,仍然可以訪問)

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

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

然後在線程1你可以問thread1:x,它會贏得成功 及線程將推出一個異常(你可以捕捉它,並說失敗...)(除非你不定義X動態)

另一種方法是使用thread_local ......但你必須定義每個子句thread_local(無聊!)