2012-10-02 79 views
1

我開發了一個帶多線程的boost.python C/C++程序。從線程提升python /導入模塊需要ReleaseLock()。爲什麼?

main(),我創建一個線程:

PyEval_InitThreads();

pthread_create(& id,& detached_attr,newThread,NULL);

·在newThread()中,我調用了兩個Py_ *函數。

Py_Initialize();

PyGILState_STATE gstate = PyGILState_Ensure();

然後,我打電話叫hoge() C++函數中newThread()

void hoge(){ 
    py::object main_module; 
    py::object main_namespace; 

    try { 
     main_module = py::import("__main__"); //segmentation fault 
     main_namespace = main_module.attr("__dict__"); 
    } catch (py::error_already_set const &) { 
     PyErr_Print(); 
    } 

    //Some boost python code 
} 

GDB回溯輸出是在這裏。

(gdb) bt 
#0 0x4032fe24 in __ctype_b_loc() from /lib/libc.so.6 
#1 0x4032fde8 in __ctype_b_loc() from /lib/libc.so.6 

爲什麼import()失敗?我不知道。請告訴我如何解決這個問題。



--edit 28年12月12日---

我使用下面的方法解決了這個問題。

main(),我執行

Py_Initialize(); 
PyEval_InitThreads(); 
PyEval_ReleaseLock(); 

然後,我創建了新的線程。在新的線程,我執行

PyGILState_STATE gstate = PyGILState_Ensure(); 
CALL SOME PYTHON CODE 
PyGILState_Release(gstate); 

但我不知道爲什麼現在的作品。有人能告訴我原因嗎?

+1

我建議先嚐試更簡單的例子。例如,試着讓沒有線程的代碼片段運行。一旦一切按預期工作(測試!),然後嘗試多線程。 –

+0

謝謝你的建議。 我可以解決這個問題。 – fantajista

+0

你是如何解決你的問題的?我有同樣的問題.. –

回答

0

與許多其他解釋型語言一樣,Python通過使用全局解釋器鎖(或GIL)實現線程安全性(see this wiki),該鎖可阻止並行操作兩個python解釋器調用。所以,你發出的任何python調用應該首先請求鎖,執行你的命令,然後釋放鎖。你必須遵守這個規則,否則你可能會讓口譯人員崩潰,就像你在你的例子中所做的那樣。注意你的函數hoge()沒有請求GIL,因此崩潰。現在,使用GIL請求(或「確保」)和釋放函數調用來包裝代碼並不能解決所有問題 - 您仍然需要確保當您有2個線程時,兩個都將有權訪問GIL。如果你不會在主線程中釋放GIL,那麼你的第二個線程會被永遠阻塞!你嘗試過嗎?如果沒有,你可以做它看看會發生什麼。

正確的解決方案 - 您自己找到的解決方案是在每個線程獲取並釋放GIL,並確保您不會卡在其中一個GIL線程中,而其他線程正在餓死。

相關問題