【问题标题】:Can I have two multithreaded functions running at the same time?我可以同时运行两个多线程函数吗?
【发布时间】:2014-10-16 16:54:49
【问题描述】:

我对多线程非常陌生。我的 python 脚本中有 2 个函数。一个函数enqueue_tasks 遍历一个大的小项目列表,并对每个项目执行一项任务,该任务涉及将项目附加到列表中(我们称之为master_list)。这个我已经使用futures多线程了。

executor = concurrent.futures.ThreadPoolExecutor(15) # Arbitrarily 15
futures = [executor.submit(enqueue_tasks, group) for group in grouper(key_list, 50)]
concurrent.futures.wait(futures)

我还有另一个函数process_master 遍历上面的master_list 并检查列表中每个项目的状态,然后执行一些操作。

我可以使用上面相同的方法为process_master 使用多线程吗?此外,我可以让它与enqueue_tasks 同时运行吗?这意味着什么? process_master 依赖于来自enqueue_tasks 的列表,那么同时运行它们会不会有问题?有没有办法可以稍微延迟第二个功能? (也许使用time.sleep)?

【问题讨论】:

    标签: python multithreading multiprocessing


    【解决方案1】:

    不,这不安全。如果enqueue_tasksprocess_master 同时运行,您可能会在enqueue_tasks 内向master_list 添加项目,同时process_master 正在对其进行迭代。在迭代时更改可迭代对象的大小会导致 Python 中出现未定义的行为,因此应始终避免。您应该使用threading.Lock 来保护将项目添加到master_list 的代码以及迭代master_list 的代码,以确保它们不会同时运行。

    更好的是,使用Queue.Queue(Python 3.x 中的queue.Queue)而不是list,这是一种线程安全的数据结构。将项目添加到enqueue_tasks 中的Queueprocess_masterQueue 中的get 项目。这样process_master 可以与enqueue_tasks 在同一时间安全运行。

    【讨论】:

    • 啊 Queue.Queue 看起来真的很不错——如果使用它,我就不必实现任何手动锁定机制了吗?另外,如果我在一个脚本中使用两个多线程操作,我应该如何选择线程数?我这里随意选择了15,但是如果我有两个进程在运行,我应该为每个做7吗?我的逻辑在这里有缺陷吗?
    • @jeffrey 对,Queue.Queue 不需要锁定。您应该选择的线程数(以及您应该使用ThreadPoolExecutor 还是ProcessPoolExecutor)取决于您在enqueue_tasksprocess_master 中所做的事情。如果您正在执行 CPU 密集型工作,您应该使用 ProcessPoolExecutormultiprocessing.Queuemultiprocessing.cpu_count() 进程。
    • @jeffrey 由于全局解释器锁 (GIL),一次只能实际执行一个 Python 线程,因此如果您使用 CPU,则不会从多线程中获得任何性能优势绑定任务。使用多个进程而不是线程可以解决 GIL 的限制。 GIL 可以在阻塞 I/O 期间释放,因此线程仍然有用。
    • 我明白了,那么我将不得不试验 ThreadPoolExecutor 或 ProcessPoolExecutor 是否适合我。但为了澄清一下,如果我使用线程安全的数据结构,那么使用多进程并同时运行多个函数是完全没问题的?
    • @jeffrey 如果您使用多个进程,则需要使用 process-safe 数据结构。所以,multiprocessing.Queue 而不是 Queue.Queue
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多