Python嵌入线程 - 避免死锁?

时间:2009-04-29 18:09:33

标签: python multithreading deadlock embedding

有没有办法嵌入python,允许从python到C ++的回调,允许Pythhon代码产生线程,并避免死锁?

问题在于:

  • 要调用Python,我需要持有GIL。通常,我通过在第一次创建解释器时获取主线程状态,然后在调用Python之前使用PyEval_RestoreThread()获取GIL并交换线程状态来执行此操作。

  • 从Python调用时,我可能需要访问受主机中单独的关键部分保护的一些受保护资源。这意味着Python将保留GIL(可能来自我最初调用的其他线程),然后尝试获取我的保护锁。

  • 在调用Python时,我可能需要保持相同的锁,因为我可能正在迭代某些对象集合,例如。

问题在于,即使我在调用Python时持有GIL,Python也可能放弃它,将其交给另一个线程,然后将该线程调用到我的主机中,期望获取主机锁。同时,主机可以接受主机锁和GIL锁,并调用Python。随之而来的是死锁。

这里的问题是,当我调用它时,Python将GIL放弃到另一个线程。这就是它所期望的,但它使得无法对锁定进行排序 - 即使我先使用GIL,然后自己锁定,然后调用Python,Python将从另一个线程调用我的系统,期望自己锁定(因为它通过释放它来解除GIL的顺序)。

我无法让系统的其余部分使用GIL来处理系统中所有可能的锁 - 这甚至都行不通,因为Python仍然可以将它发布到另一个线程。

我无法保证我的主机在输入Python时也没有任何锁定,因为我无法控制主机中的所有代码。

那么,是不是这样做呢?

3 个答案:

答案 0 :(得分:2)

“在调用Python时,我可能需要保持相同的锁,因为我可能正在迭代某些对象集合,例如。”

这通常表明具有多个线程的单个进程不合适。也许这是一种情况,其中多个进程 - 每个进程都具有来自集合的特定对象 - 更有意义。

独立流程 - 每个流程都有自己的线程池 - 可能更容易管理。

答案 1 :(得分:2)

python调用的代码应在释放任何锁之前释放GIL。 这样我相信它无法进入死锁。

答案 2 :(得分:-1)

最近在pyopenssl列表上讨论了类似的问题。我担心如果我试图解释这个我会弄错,所以相反我会把你推荐给the problem in question