【发布时间】:2014-04-04 11:26:38
【问题描述】:
在我开始描述我的问题之前,值得一提的是我使用的是 Python 2.7。我没有检查,但这可能与 Python 3.x 无关。
在使用 Python 的 Queues 时,我发现了一些奇怪的东西。通常,当从队列中获取一个对象时,我允许长时间但有限的超时(例如几秒钟),以便在没有找到对象的情况下进行调试和错误报告,而这是预期的。我发现有时在将对象插入到以前为空的队列中的时间与同一队列的 get 方法返回该对象的时间之间存在奇怪的差距,即使该方法是在为该对象调用 put 之前调用。
稍微挖掘一下,我发现这个空隙是通过睡觉来填补的。在Queue 模块中,如果传递给get 方法的timeout 参数不是None,并且是正数,则使用non_empty Condition 的wait 方法调用正参数(这不是 100% 精确的;事实上,Queue 的“_qsize”方法,它返回底层 deque 的长度首先验证返回 0,但只要队列是首先是空的,接下来就是条件的等待)。
Conditions 的wait 方法在是否超时时会有所不同。如果它没有得到任何超时,它只是调用waiter.acquire。这是在C 中定义的,超出了我的理解,但它似乎可以正常工作。但是,如果给定超时 ,则会发生奇怪的睡眠序列,此时睡眠时间以任意大小(1 毫秒)开始,并且随着时间的推移变得更长。这是运行的确切代码:
# Balancing act: We can't afford a pure busy loop, so we
# have to sleep; but if we sleep the whole timeout time,
# we'll be unresponsive. The scheme here sleeps very
# little at first, longer as time goes on, but never longer
# than 20 times per second (or the timeout time remaining).
endtime = _time() + timeout
delay = 0.0005 # 500 us -> initial delay of 1 ms
while True:
gotit = waiter.acquire(0)
if gotit:
break
remaining = endtime - _time()
if remaining <= 0:
break
delay = min(delay * 2, remaining, .05)
_sleep(delay)
这显然是我发现新对象放入先前空队列的时间与已调用的 get 方法返回该对象的时间之间存在差距的原因。随着延迟时间呈指数增长,直到被 0.05 秒的巨大(从我的角度)大小阻塞,它会在我的应用程序的生命周期中产生令人惊讶且不需要的重要睡眠。
你能解释一下这样做的目的是什么吗? Python 开发人员是否假设没有 Python 用户会关心这样的时间长度?是否有快速解决方法或适当的修复方法?你建议我重载线程模块吗?
【问题讨论】:
标签: python python-2.7 sleep python-multithreading