我的理解是,典型的 GIL 操作涉及,例如,阻塞 I/O 操作。因此,人们会希望在 I/O 操作之前释放锁,并在它完成后重新获取它。
我目前面临着一个带有 C 扩展的不同场景:我正在创建通过 Canvas
类向 Python 公开的 X 窗口。在实例上调用方法 show()
时,将使用 PyThreads
启动一个新的 UI 线程(调用 PyThread_start_new_thread
)。这个新线程负责在 X 窗口上绘图,使用 Canvas
子类的 on_draw
方法中指定的 Python 代码。纯 C 事件循环在主线程中启动,它只检查 X 窗口上的事件,暂时只捕获 WM_DELETE_EVENT
。
所以我可能有很多线程(每个 X 窗口一个)想要执行 Python 代码,而主线程根本不执行任何 Python 代码。
如何释放/获取 GIL 以允许 UI 线程有序地进入解释器?
最佳答案
规则很简单:您需要持有 GIL 才能访问 Python 机制(任何以 Py<...>
和任何 PyObject
开头的 API)。
因此,您可以在不需要时释放它。
比这更进一步的是 fundamental problem of locking granularity :潜在的好处与锁定开销。 There was an experiment for Py 1.4 to replace the GIL with more granular locks that failed exactly because the overhead proved prohibitive.
这就是为什么它通常为涉及调用的代码块释放它可能需要任意时间的扩展设施(特别是如果它们涉及等待外部事件)——如果你不释放锁,Python 将只是空转在此期间。
注意这个规则,你会自动达到你的目标:每当一个线程不能继续进行时(无论是 I/O,来自另一个线程的信号,甚至是 time.sleep()
以避免忙循环) ,它将释放锁并允许其他线程代替它继续进行。 GIL分配机制力争为fair (请参阅 issue8299 探索它的公平性),让程序员不必为任何完全源于引擎的偏见而烦恼。
关于python - 当需要执行多个线程时如何操作GIL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50430271/