如果它经常睡觉,Windows是否可以完全停止?

时间:2013-07-29 07:45:14

标签: c++ multithreading boost tbb

我在一个多线程应用程序中有一个罕见的heisenbug,主线程,只有这个线程,什么都不做。因为它是一个heisenbug,所以很难理解为什么会这样。

主线程基本上只是循环。在循环中,它检查几个并发优先级队列,其中包含按时间排序的任务。它会弹出一个任务,看看是否该执行它。如果是时候,它只会将它安排到TBB的任务调度程序中(使用root任务,这是所有其他任务的父级)。如果不是时间,则在优先级队列中再次推送任务。 这是一个周期。在循环结束时,主线程会在很短的时间内进入休眠状态,我希望在实践中会更长,但这并不是真正的问题,我只是不希望它在没有必要时使用太多资源。

Litterally:

    static const auto TIME_SCHEDULED_TASKS_SPAWN_FREQUENCY = microseconds(250);


    while( !m_task_scheduler.is_exiting() ) // check if the application should exit
    {
        m_clock_scheduler.spawn_realtime_tasks(); // here we spawn tasks if it's time 
        this_thread::sleep_for( TIME_SCHEDULED_TASKS_SPAWN_FREQUENCY );
    }

    m_clock_scheduler.clear_tasks();
    m_root_task.wait_for_all();

我有一项特殊任务,每秒只记录一条“TICK”消息。它会自动重新安排,直到程序结束。然而,当heisenbug出现时,我可以看到“TICK”消失,应用程序除了在非主线程中发生的工作之外没有做任何其他事情。所以似乎只触及主线程。

问题可能来自不同的地方,可能是在调度逻辑中,但它也是唯一具有睡眠调用的线程。那个睡眠是一个boost :: this_thread :: sleep_for()。

我的问题是:是否有可能Windows(7 64位)认为主线程经常睡觉并决定它应该睡觉的时间比要求的时间长或者肯定会结束?

我希望这是不可能的,但我想确定。到目前为止,我在在线文档中没有找到任何精确度。


更新

我有一个朋友可以系统地重现这个错误(在Windows Vista,Core 2 Duo上)。我发送了一个没有睡眠的版本和另一个使用condition_variable重新实现主循环的版本,这样每次在队列中推送任务时,condition_variable都会唤醒主线程(但仍然有最小的生成时间)。

没有睡眠的版本有效(但速度较慢) - 所以即使我不知道真正的来源,这个问题似乎也有关系。

使用condition_variable的版本有效 - 这表明睡眠调用无法正常工作?

所以,显然我修复了这个bug,但我仍然不知道为什么特定的睡眠调用有时会阻塞。


更新:

这实际上是由Boost代码触发的错误。我抓住了这个bug并报告了它并且它已被修复。我没有检查以前的版本,但它已在Boost 1.55中修复

1 个答案:

答案 0 :(得分:3)

  

Windows(7 64位)是否有可能认为主线程经常处于休眠状态,并且认为它应该睡眠的时间比询问要长或者肯定会结束?

NO。这不会发生。 MSDN并未表明可能会发生这种情况。根据经验,我有许多Windows应用程序,其周期间隔从ms到几小时不等。你建议的效果不会发生 - 这对我的应用程序来说是灾难性的。

鉴于Sleep()的众所周知的粒度问题需要非常短的间隔,睡眠线程将在间隔到期时准备就绪。如果有可用的CPU核心(即核心并未全部运行正在运行更高优先级的线程),则新准备好的线程将运行。

操作系统不会延长Sleep()的间隔,因为任何与线程状态相关的历史/统计数据 - 我认为它不会保留任何此类数据。