Python time.sleep - 永远不会醒来

时间:2010-02-26 14:50:50

标签: python multithreading deadlock sleep

我认为这将是那些简单的问题之一,但它让我感到困惑。

[ STOP PRESS:我是对的。解决方案被发现。查看答案。]

我使用Python的unittest框架来测试多线程应用程序。很好,很直接 - 我有5个左右的工作线程监视一个公共队列,还有一个生产者线程为它们制作工作项。生产者线程由测试用例触发。

在此测试中,只有一个任务被放入队列中。它在测试中所做的处理只是实际处理的存根,因此工作线程执行5秒睡眠以模拟任务真正完成之前所经过的时间,并且线程将准备好进行另一项任务

代码片段是:

 logging.info("Sleep starting")
 time.sleep(5)
 logging.info("Waking up")

现在奇怪的部分。我看到“睡眠启动”日志消息,但没有看到唤醒消息。程序锁定并且不响应键盘中断(CTRL + C)。 CPU负载非常低。

我在Windows和Ubuntu(Python 2.6.2)中看到了同样的问题。

我考虑过是否发生异常并被隐藏,所以我在第一行和第二行之间添加“print 1/0” - 我看到提出了Division By Zero错误。我把它移到睡眠后,我从来没有看到这个消息。

我想“好吧,也许其他线程试图同时记录非常大的东西,它仍然在缓冲。它在做什么?”

那么,到目前为止,测试已经返回到unittest,在测试系统状态之前暂停等待线程开始。

 logging.info("Test sleep starting")
 time.sleep(0.25)
 logging.info("Test waking up")
哇,看起来很熟悉。它以完全相同的方式冻结!第一条日志消息出现,第二条消息不出现。

我最近对该单元进行了重大改写,所以我无法声称“我没有触及任何东西”,但我在改变中看不到任何不适。

可疑区域:

  • 我包括使用Threading.Lock(因为我不知道如何推理GIL的安全性,所以我坚持我所知道的。我没有看到任何关于我的代码的“僵局”。

    < / LI>
  • 我是Python的unittest框架的新手。它是否可以用于重定向日志记录或可能模拟这些症状的类似事件?

  • 不,我没有替换非标准时间模块!

什么会阻止线程被唤醒?还有什么我错过了?

2 个答案:

答案 0 :(得分:5)

叹息。

工人线程#1正在睡觉,然后醒来。然后它将记录唤醒消息,并被阻止。一次只能记录一个线程。

UnitTest线程正在睡眠,之后就会醒来。然后它将记录唤醒消息,并被阻止。一次只能记录一个线程。

工作者 - 线程 - 先前未提及 - 问题#2正在悄悄地完成处理队列中的PREVIOUS项目,而第一个工作线程正在休眠。它得到了一个日志声明。其中一个参数是一个对象,并且隐式调用了str()。该对象上的 str ()函数有一个bug;它访问了一些数据成员时陷入僵局。在由日志记录功能处理时发生死锁,从而保持日志记录线程锁定,并使其看起来像其他线程从未醒过。

零分测试没有区别,因为它的结果是尝试记录。

答案 1 :(得分:-3)

在Linux上,尝试将I / O调度程序更改为完全公平排队(CFQ)。

echo cfq > /sys/block/sda/queue/scheduler