在单独的 GIL 中执行非 GUI 线程

问题描述 投票:0回答:1

我的团队开发了一个 GTK-Python 应用程序,可以动态生成线程来处理运行时间较长的任务。最近,我们添加了一项按需请求批量计算的功能,这导致 GUI 没有响应。我的研究和分析表明,问题似乎是对 GIL 的争用,导致 GUI 线程饥饿。我们正在考虑的最便宜的解决方案是将我们的自定义线程移动到另一个进程/GIL,以便 GUI 框架生成的线程在一个进程中运行,但我们的动态生成线程在另一个进程中运行。

我一直在阅读多处理文档,但我没有想到任何支持这种开箱即用的功能。我应该探索哪些选项?

python multithreading gil
1个回答
0
投票

这是一种可能性。您创建一个子进程

thread_creator
,其目的是创建子线程。这是通过向
thread_creator
传递一个
multiprocessing.Queue
实例来实现的,该实例将包含指定要创建的新子线程的参数的元组。 None 的特殊
sentinel
值是
thread_creator
进程终止的信号。当它创建的所有非守护线程终止时,子进程及其创建的所有守护线程都将终止。

在下面的代码中,我们创建一个非守护线程

sample_threaded_worker
,它将在 0.5 秒后终止,以及一个守护线程
another_threaded_worker
,每 0.1 秒连续循环打印一条消息。在要求
thread_creator_process
终止后,它会在
sample_threaded_worker
完成后立即终止。当这种情况发生时,
another_threaded_worker
将自动终止。因此
another_threaded_worker
将执行大约 0.5 秒,并打印出大约 5 条消息:

from multiprocessing import Process, Queue
from threading import Thread
import time

def sample_threaded_worker(x=1, y=2, debug=False):
    time.sleep(.5)
    if debug:
        print('sample_threaded_worker', x, y)

def another_threaded_worker():
    while True:
        print('another_threaded_worker', time.time())
        time.sleep(.1)

def thread_creator(queue):
    while True:
        request = queue.get()
        if request is None:
            break
        # Unpack
        target, args, kwargs, daemon = request
        Thread(target=target, args=args, kwargs=kwargs, daemon=daemon).start()

def create_thread(queue, target=None, args=(), kwargs={}, daemon=None):
    """Helper function to create a child thread in the child process."""

    queue.put((target, args, kwargs, daemon))

def main():
    queue = Queue()
    p = Process(target=thread_creator, args=(queue,))
    p.start()
    create_thread(queue, target=sample_threaded_worker, args=(5, 9), kwargs={'debug': True})
    create_thread(queue, target=another_threaded_worker, daemon=True)
    # Terminate process. All daemon threads that have been created will be killed
    # when all non-daemon threads have completed.
    queue.put(None)
    p.join()

if __name__ == '__main__':
    main()

打印:

another_threaded_worker 1718880689.7697933
another_threaded_worker 1718880689.87115
another_threaded_worker 1718880689.9717884
another_threaded_worker 1718880690.0727093
another_threaded_worker 1718880690.1730008
sample_threaded_worker 5 9
© www.soinside.com 2019 - 2024. All rights reserved.