私はマルチスレッドのCアプリケーションにPythonインタプリタを埋め込みました。スレッドの安全性を確保するために使用するAPIについて少し混乱しています。マルチスレッドのCアプリケーションにPythonを埋め込む
私が集めたところから、Pythonを埋め込むときに、他のPython C API呼び出しを呼び出す前にGILロックを処理するのは組み込み関数です。これは次の関数で行われます。
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
しかし、これだけでは十分ではないようです。私はPython APIの相互排除を提供していないようだから、まだランダムなクラッシュを受けています。
いくつかのより多くのドキュメントを読んだ後、私も追加:右Py_IsInitialized()
を呼び出した後
PyEval_InitThreads();
をしかし紛らわしい部分が出番です。 。
初期化とグローバルインタプリタロックを獲得
これは時にこの関数が戻り、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()'デッドロックです。 – khkarens
これは、Pythonの組み込みと拡張モジュールへの呼び出しの両方で機能する唯一のものです。 –