Для загрузки модуля python / import из потока требуется ReleaseLock (). Зачем?

Я разрабатываю программу boost.python C / C ++ с многопоточностью.

В main()Я создаю тему:

PyEval_InitThreads ();

pthread_create ( &Я бы, &detached_attr, newThread, NULL);

New В newThread () я вызываю две функции Py_ *.

Py_Initialize ();

PyGILState_STATE gstate = PyGILState_Ensure ();

Затем я вызываю функцию C ++ с именем hoge() в 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() потерпеть поражение? Я понятия не имею. Подскажите пожалуйста как решить эту проблему.

—редактировать 12/12/28 —

Я решил эту проблему, используя следующий метод.

В main()Я исполняю

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

Затем я создаю новую тему. В новой теме я выполняю

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

Но я не знаю Зачем это работает сейчас. Может ли кто-нибудь сказать мне причину?

1

Решение

Python, как и многие другие интерпретируемые языки, обеспечивает безопасность потоков (увидеть эту вики), используя глобальную блокировку интерпретатора (или GIL), которая мешает двум вызовам интерпретатора Python работать параллельно. Таким образом, любой вызов Python, который вы делаете, должен сначала запросить блокировку, выполнить ваши команды, а затем снять блокировку. Вы должны следовать этому правилу, иначе вы можете разбить переводчик, как вы это делали в своем примере. Обратите внимание, что ваша функция hoge() не просил GIL, поэтому крушение.

Теперь, оборачивая ваш код GIL-запросом (или «обеспечить») и вызывая вызовы функций, это не решает все — вы все равно должны убедиться, что, когда у вас есть 2 потока, это и то и другое будет иметь доступ к GIL. Если бы вы не выпустили GIL в главном потоке, ваш второй поток, который фактически выполняет Python, будет заблокирован навсегда! Вы пробовали это? Если нет, вы можете просто посмотреть, что произойдет.

Правильное решение — то, которое вы нашли самостоятельно, — это получить и выпустить GIL в каждом потоке и убедиться, что вы не застряли в одном из потоков с GIL, в то время как другие голодают.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]