【问题标题】:Python embedding with threads -- avoiding deadlocks?Python 嵌入线程——避免死锁?
【发布时间】:2009-04-29 18:09:33
【问题描述】:

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

问题是这样的:

  • 要调用 Python,我需要持有 GIL。通常,我首先创建解释器时获取主线程状态,然后使用 PyEval_RestoreThread() 获取 GIL 并在调用 Python 之前交换线程状态。

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

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

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

这里的问题是,当我调用 GIL 时,Python 将 GIL 放弃给另一个线程。这就是它所期望的,但是它使得不可能进行序列锁定——即使我先使用 GIL,然后使用我自己的锁,然后调用 Python,Python 将从另一个线程调用我的系统,期望使用我自己的锁(因为它通过释放 GIL 来取消对 GIL 的排序)。

我不能真正让系统的其余部分使用 GIL 来处理系统中所有可能的锁 - 这甚至不能正常工作,因为 Python 可能仍会将其释放到另一个线程。

我也不能真正保证我的主机在进入 Python 时不会持有任何锁,因为我无法控制主机中的所有代码。

那么,难道就只有这样就做不到了吗?

【问题讨论】:

  • 您能否要求您的 C++ 代码在获取主机锁之前持有 GIL?

标签: python multithreading deadlock embedding


【解决方案1】:

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

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

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

【讨论】:

  • 一个进程正是我所需要的(有问题的进程实际上是一个网络浏览器插件)。因此,很遗憾,您的建议不能回答或适用于我的问题。
  • 请用其他事实更新您的问题——不要在 cmets 中添加信息。 “网络浏览器插件”是新信息,属于问题。
【解决方案2】:

python 调用的代码应该在获取任何锁之前释放 GIL。 这样我相信它不会陷入僵局。

【讨论】:

  • 好答案。请记住,GIL 的存在只是为了保护 Python 解释器的内部数据结构。如果一个线程调用了一些非 Python 代码,它可以在该代码执行时安全地释放 GIL。
【解决方案3】:

最近在 pyopenssl 列表上有一些类似问题的讨论。恐怕如果我试图解释这一点,我会弄错,所以我将把你推荐给the problem in question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-02
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多