【问题标题】:Why does Python's Queue return an approximate size in qsize()?为什么 Python 的队列在 qsize() 中返回一个近似大小?
【发布时间】:2012-07-21 11:54:37
【问题描述】:

在 qsize() 的 doc 中它说:返回队列的近似大小。

为什么它不能只返回这个队列的确切大小?我知道队列可能被多个线程访问,但在我调用该函数的那一刻,我认为它仍然可以返回那个时刻的确切大小。

【问题讨论】:

  • 什么时候?队列大小可能在方法返回期间发生了变化。

标签: python multithreading


【解决方案1】:

正是因为有其他线程在访问它。当您尝试使用从 qsize() 返回的大小时,队列可能已经改变。如果文档是这样写的会更好:

返回队列的大小。请注意,在多线程环境中,大小可以随时更改,这只是实际大小的近似值。

【讨论】:

    【解决方案2】:

    我同意“近似”不是最清晰的词选择,但正如 Ned 提到的,他们试图指出,仅仅因为 t1 时队列的大小为 7 并不意味着它仍然会当您稍后推送或弹出值时,大小为 7。

    问题在于,假设您从 qsize 返回的大小仍然正确,当您从该队列中推送/弹出一个值时,可能会在多线程环境中出现意外行为。

    例如:

    q = Queue()
    if q.qsize > 0: # size is 1 here
        # another thread runs here and gets an item from your queue
        # this get fails and throws an exception in your thread:
        item = q.get(False)
        # do whatever processing with item you need to do
    

    这是一个 LBYL 的示例“在你跳跃之前先看一下”,它很危险,因为当多个线程访问队列时,这里可能会出现竞争条件。

    在这种情况下,您应该支持 EAFP 或“请求宽恕比请求许可更容易”并执行以下操作:

    from Queue import Queue, Empty
    import time
    q = Queue()
    try:
        item = q.get(False)
        # do whatever processing with item you need to do 
    except Empty:
        time.sleep(1)
    

    【讨论】:

    • .. 或者只是使用信号量来保证队列有一个条目。
    • 队列已经同步,不要在上面添加更多。在异常情况下使用q.get 是获取项目的最佳线程安全方式。
    • @NedBatchelder 我不明白你的评论。这正是这里所做的,不是吗?
    • 我认为如果队列不为空,但另一个线程正在访问它(例如放置另一个项目),get 方法也可以阻塞。在这种情况下,尽管队列不为空,但似乎仍然抛出了 Empty 异常。
    猜你喜欢
    • 2014-01-05
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 2020-08-05
    • 2015-04-12
    • 1970-01-01
    相关资源
    最近更新 更多