【问题标题】:is python ThreadPoolExecutor thread safe?python ThreadPoolExecutor 线程安全吗?
【发布时间】:2017-07-24 17:11:43
【问题描述】:

就像我应该在futures写入同一个文件时手动添加锁以保证他们一个一个地写入它?

  • 我的意思是 concurrent.futures.ThreadPoolExecutor

  • 而且我知道 java 执行器是线程安全的

一个例子:

def task():
    with open("somefile", "a") as fh:
        fh.write(part_of_data)
    do_something()
    with open("somefile", "a") as fh:
        fh.write(other_data)

在这个例子中,当在 ThreadPoorExecuter 中执行任务时,我想确保每个 other_data 都附加到 part_of_data 旁边

我不确定with语句是否是原子操作,但如果不是,执行器也应该保证文件正确打开和关闭

【问题讨论】:

  • 你能澄清你想要做什么,因为对于某些事情它是线程安全的,对于其他事情 - 不是那么多。从技术上讲,所有 Python(至少是 CPython)都是线程安全的,因为后台有可怕的 GIL 可以防止任何两个线程同时运行,但这并不排除非原子的部分结果和数据损坏的可能性操作。
  • 如果配置为 max_workers=1,ThreadPoolExecutor 一次只会运行一个任务。否则,任务可以在不同的线程中同时运行,您将需要额外的锁定。这将与工人池的想法相矛盾,因为这可能会在持有锁的时间内阻塞一个工人。而且,顺便说一句:Java 中的 ThreadPoolExecutor 在这方面具有相同的行为。

标签: python multithreading concurrency


【解决方案1】:

这是我在查看标准库中的实现 of the ThreadPoolExecutor 后的研究:

shutdown() 方法是线程安全的,因为它在修改共享状态之前需要一个锁。

submit() 方法仅在某些操作中是线程安全的,但在实践中它并不重要。当您提交要在线程池中执行的新函数时,您的函数将被放置在线程安全queue.SimpleQueue 的实例中。工作线程然后阻塞在这个队列上等待弹出提交的函数来执行它们。因为队列是线程安全的,所以提交函数的分派是线程安全的,这意味着您提交的函数都不会被孤立(不执行)或执行两次。

不是线程安全的部分是内部_adjust_thread_count() 方法。它可以同时从两个不同的线程调用,创建一个竞争,两个线程都看到num_threads < self._max_workers,并且都创建新线程来填满线程池。但是,如果这种情况发生,那也没关系,因为它只会导致线程池中出现额外的线程。对于大多数项目来说,这几乎不是问题。

【讨论】:

  • _adjust_thread_count 方法至少在 python 3.8 上以 if self._idle_semaphore.acquire(timeout=0): 开头。
猜你喜欢
  • 2010-12-14
  • 1970-01-01
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-15
  • 2011-05-02
  • 1970-01-01
相关资源
最近更新 更多