为什么Python的queue.get()函数要检查获取not_empty锁的with块内队列是否不为空?

发布于 2025-01-14 00:56:00 字数 1613 浏览 3 评论 0原文

我试图更好地理解队列库,所以这里的代码让我摸不着头脑:

def get(self, block=True, timeout=None):
        '''Remove and return an item from the queue.
        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until an item is available. If 'timeout' is
        a non-negative number, it blocks at most 'timeout' seconds and raises
        the Empty exception if no item was available within that time.
        Otherwise ('block' is false), return an item if one is immediately
        available, else raise the Empty exception ('timeout' is ignored
        in that case).
        '''
        with self.not_empty: # <-------- notice this lock guarantees the queue is not empty
            if not block:
                if not self._qsize():
                    raise Empty
            elif timeout is None:
                while not self._qsize(): # <---------- so then why is this necessary?
                    self.not_empty.wait()
            elif timeout < 0:
                raise ValueError("'timeout' must be a non-negative number")
            else:
                endtime = time() + timeout
                while not self._qsize():
                    remaining = endtime - time()
                    if remaining <= 0.0:
                        raise Empty
                    self.not_empty.wait(remaining)
            item = self._get()
            self.not_full.notify()
            return item

根据上面的注释,我想知道为什么有必要检查队列是否不为空,如果我们已经获取了保证队列不为空的锁?我对“with”语句的理解是,它在锁 self.not_empty 上调用 .acquire() ,并且 .acquire() 会阻塞,直到锁可用。那么超时不应该在那里处理吗?

I'm trying to better understand the queue library, so here's the code that's making me scratch my head:

def get(self, block=True, timeout=None):
        '''Remove and return an item from the queue.
        If optional args 'block' is true and 'timeout' is None (the default),
        block if necessary until an item is available. If 'timeout' is
        a non-negative number, it blocks at most 'timeout' seconds and raises
        the Empty exception if no item was available within that time.
        Otherwise ('block' is false), return an item if one is immediately
        available, else raise the Empty exception ('timeout' is ignored
        in that case).
        '''
        with self.not_empty: # <-------- notice this lock guarantees the queue is not empty
            if not block:
                if not self._qsize():
                    raise Empty
            elif timeout is None:
                while not self._qsize(): # <---------- so then why is this necessary?
                    self.not_empty.wait()
            elif timeout < 0:
                raise ValueError("'timeout' must be a non-negative number")
            else:
                endtime = time() + timeout
                while not self._qsize():
                    remaining = endtime - time()
                    if remaining <= 0.0:
                        raise Empty
                    self.not_empty.wait(remaining)
            item = self._get()
            self.not_full.notify()
            return item

As per my annotations above, I'm wondering why it's necessary to check if the queue is not empty, if we've already acquired the lock guaranteeing the queue is not empty? My understanding of the "with" statement is that it calls .acquire() on the lock self.not_empty, and .acquire() blocks until the lock is available. So shouldn't timeouts be handled there?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文