【问题标题】:Best way to obtain indexed access to a Python queue, thread-safe获得对 Python 队列的索引访问的最佳方法,线程安全
【发布时间】:2010-11-20 14:33:54
【问题描述】:

我有一个队列(来自Queue 模块),我想获得对它的索引访问。 (即,能够请求队列中的第 4 项,而无需将其从队列中移除。)

我看到一个队列在内部使用了一个双端队列,而双端队列具有索引访问。问题是,我怎样才能在不(1)弄乱队列,(2)破坏线程安全的情况下使用双端队列。

【问题讨论】:

  • 为什么你使用队列而不是顺序地入队和出队?这只是线程之间的共享对象吗?
  • 我不确定您所说的“按顺序将事物入队和出队”是什么意思。我什至不明白你的第二个问题:是的,队列是线程之间共享的。
  • 队列有按顺序入队和出队的东西。 “按顺序”的概念意味着除了附加到一端并从另一端弹出之外,它们很少被访问。你为什么要打破这个关于“排队”的默认假设?
  • @S.Lott,Queue.Queue 中的排队规则旨在通过子类化进行定制——这就是 self.mutexself.queue 和 c 具有公共名称的原因:正是为了表明它们允许高级应用程序(小心地;-)自定义行为(如果 Queue 只是一个黑匣子,它将对其内部使用不同的命名方案)。
  • @Alex Martelli:谢谢,但是,我仍然对这个问题感到困惑——队列是否按顺序使用?如果不是,为什么还要考虑队列结构?仅仅因为互斥锁?为什么不使用互斥锁的其他共享对象?还是信号量?还是其他类型的锁定?如果队列的 FIFO 特性不是问题的一部分,为什么还要使用队列?

标签: python multithreading queue deque


【解决方案1】:
import Queue

class IndexableQueue(Queue):
  def __getitem__(self, index):
    with self.mutex:
      return self.queue[index]

无论索引是成功还是引发IndexError,释放互斥锁当然是至关重要的,我为此使用了with 语句。在较旧的 Python 版本中,try/finally 将用于相同的效果。

【讨论】:

  • 这么干净...我现在正在搞乱 Java 中的线程,这并不好笑。
  • 很好的答案。不幸的是,在任何地方都没有记录 Queue 适合(甚至如您所说)被子类化并可以访问其内部成员。他们的“公开”是唯一的线索。甚至在 Queue.py 模块的源代码中也没有明确说明,这是一种耻辱。您在此答案中的代码 sn-p 应该是 Queue 的标准 lib 文档中的一个示例,恕我直言
  • @eliben,你说得对,Queue.py 的内部文档是(并且长期以来)非常低效,但至少它变得更好了......例如当时我们记录了文档中没有的它的子类(食谱第 2 版中的配方 9.3),现在至少提供了几个有用的子类...;-)。
  • @Alex Martelli:我注意到互斥锁是 Lock,而不是 RLock。你认为这有充分的理由吗?如果它是一个 RLock,我可以保证在我访问它的整个会话期间没有人接触队列。你怎么看?
  • @cool-RR,问题是队列中的锁定很复杂——也有基于该互斥锁的条件。因此,在持有互斥锁的同时调用不同的 Queue 方法(我认为这是您所追求的)是有风险的事情——即使它是一个 RLock,它也可能死锁!为什么不将 self.queue 的副本复制到您自己的局部变量中(同时持有互斥锁),然后释放互斥锁并访问您的本地副本呢? (我不建议以任何方式改变 self.queue,除了“神圣”的那些,否则你还需要发出正确的条件 &c -- eep!-)。
猜你喜欢
  • 2021-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
相关资源
最近更新 更多