Я внедряю интерпретатор python в многопоточное приложение C, и я немного запутался в отношении того, какие API-интерфейсы я должен использовать для обеспечения безопасности потоков.Встраивание python в многопоточное приложение C
Из того, что я собрал, при встраивании python перед встраиванием нужно позаботиться о блокировке GIL перед вызовом любого другого вызова API Python C. Это делается с помощью этих функций:
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
Но этого, по-видимому, недостаточно. У меня все еще были случайные сбои, так как он, похоже, не предусматривает взаимного исключения для API-интерфейсов Python.
После прочтения еще нескольких докторов я также добавил:
PyEval_InitThreads();
сразу после вызова Py_IsInitialized()
, но вот где запутанная часть приходит. Документы утверждают, что эта функция:
Initialize и приобретают глобальный интерпретатор запирать
Это говорит о том, что, когда эта функции возвращает, то GIL должен быть заблокировано и должно быть разблокировано как-то. но на практике это, как представляется, не требуется. Благодаря этой линии моя многопоточная работа отлично работала, и взаимное исключение поддерживалось функциями PyGILState_Ensure/Release
.
Когда я попытался добавить PyEval_ReleaseLock()
после PyEval_ReleaseLock()
приложение с закрытыми окнами довольно быстро в последующем вызове PyImport_ExecCodeModule()
.
Так что же мне здесь не хватает?
Это неправильно и потенциально опасно: 'PyEval_SaveThread' всегда должен быть соединен с' PyEval_RestoreThread'. Как [объяснено в другом месте] (http://stackoverflow.com/a/15471525/1600898), вы не должны пытаться освободить блокировку после ее инициализации; просто оставьте его на Python, чтобы выпустить его как часть своей обычной работы. – user4815162342
Я не понимаю, почему это вредно, если вы положили все вызовы на python в блоки _Block_ _Allow_. С другой стороны, если вы не вызываете 'PyEval_SaveThread();', то ваш основной поток блокирует доступ других потоков к Python. Другими словами, 'PyGILState_Ensure()' deadlocks. – khkarens
Это единственное, что работает как для встраивания Python, так и для вызова в модуль расширения. –