15.8 Cå’ŒPythonä¸çš„线程混用¶
问题¶
ä½ æœ‰ä¸€ä¸ªç¨‹åº�需è¦�æ··å�ˆä½¿ç”¨Cã€�Python和线程, 有些线程是在Cä¸åˆ›å»ºçš„,超出了Python解释器的控制范围。 并且一些线程还使用了Python C APIä¸çš„函数。
解决方案¶
å¦‚æžœä½ æƒ³å°†Cã€�Python和线程混å�ˆåœ¨ä¸€èµ·ï¼Œä½ 需è¦�ç¡®ä¿�æ£ç¡®çš„åˆ�始化和管ç�†Python的全局解释器é”�(GIL)。 è¦�æƒ³è¿™æ ·å�šï¼Œå�¯ä»¥å°†ä¸‹åˆ—代ç �æ”¾åˆ°ä½ çš„C代ç �ä¸å¹¶ç¡®ä¿�它在任何线程被创建之å‰�被调用。
#include <Python.h>
...
if (!PyEval_ThreadsInitialized()) {
PyEval_InitThreads();
}
...
对于任何调用Python对象或Python C APIçš„C代ç �,确ä¿�ä½ é¦–å…ˆå·²ç»�æ£ç¡®åœ°èŽ·å�–和释放了GIL。
这�以用 PyGILState_Ensure() 和 PyGILState_Release() ��到,如下所示:
...
/* Make sure we own the GIL */
PyGILState_STATE state = PyGILState_Ensure();
/* Use functions in the interpreter */
...
/* Restore previous GIL state and return */
PyGILState_Release(state);
...
�次调用 PyGILState_Ensure() 都�相应的调用 PyGILState_Release() .
讨论¶
在涉å�Šåˆ°Cå’ŒPython的高级程åº�ä¸ï¼Œå¾ˆå¤šäº‹æƒ…一起å�šæ˜¯å¾ˆå¸¸è§�的—— å�¯èƒ½æ˜¯å¯¹Cã€�Pythonã€�C线程ã€�Python线程的混å�ˆä½¿ç”¨ã€‚ å�ªè¦�ä½ ç¡®ä¿�解释器被æ£ç¡®çš„åˆ�始化,并且涉å�Šåˆ°è§£é‡Šå™¨çš„C代ç �执行了æ£ç¡®çš„GIL管ç�†ï¼Œåº”该没什么问题。
è¦�注æ„�的是调用 PyGILState_Ensure() å¹¶ä¸�会立刻抢å� æˆ–ä¸æ–解释器。
如果有其他代ç �æ£åœ¨æ‰§è¡Œï¼Œè¿™ä¸ªå‡½æ•°è¢«ä¸æ–知é�“那个执行代ç �释放掉GIL。
在内部,解释器会执行周期性的线程切æ�¢ï¼Œå› æ¤å¦‚果其他线程在执行,
调用者最终还是å�¯ä»¥è¿�行的(尽管å�¯èƒ½è¦�å…ˆç‰ä¸€ä¼šï¼‰ã€‚