如何保证精确的线程睡眠间隔?

时间:2017-08-08 14:33:58

标签: c++ c++11 condition-variable

通常,如果我想模拟某些作品或等待确切的时间间隔,我会使用condition_variable::wait_for或最差thread::this_thread::sleep_for。但condition_variable documentation声明wait_forwait_until方法可能阻止的时间超过要求的时间。

  

由于调度或资源争用延迟,此函数可能会阻止比更长的

如何确保准确的等待间隔?

更新

我可以在没有condition_variable的情况下联系吗?

4 个答案:

答案 0 :(得分:7)

你不能这样做。

为了获得这样的确切保证,您需要一个实时操作系统。

C ++并不保证您使用的是实时操作系统。

因此它提供了典型的非RTOS提供的保证。

请注意,在RTOS上进行编程还有其他一些问题,远远超出了本问题的范围。

在实践中,当人们真正想要细粒度的时序控制(比如,他们正在使用每帧或每扫描线缓冲器或类似物,或音频缓冲器或其他任何东西)时,有一件事就是检查时间很短,如果是这样,旋转等待。如果时间较长,他们等待的时间少于他们想要等待的时间,然后醒来并旋转。

这也不能保证有效,但几乎适用于所有情况。

在RTOS上,平台可以提供您想要的原语。这些不在标准C ++的范围之内。没有典型的桌面操作系统是我所知道的RTOS。如果您正在为战斗机的控制硬件或类似设备编程,您可能正在使用RTOS进行编程。

我希望你不要编写战斗机控制软件并在堆栈溢出时询问这个问题。

答案 1 :(得分:0)

如果假设确实在某个确切的持续时间内进行了睡眠,然后在响应中执行了某些操作(例如获取当前时间或在屏幕上打印消息),则该操作可能会延迟一段未知的时间例如由于处理器负载。这相当于(几乎)立即发生的动作,但计时器花费的时间比预期的要长。即使在最佳情况下,计时器在您请求的时间完成,并且操作系统允许您的操作完成而不会抢占您的过程,但执行该操作需要几个时钟周期。

换句话说,在标准操作系统上,计时器在准确的时间内完成是不可能的,甚至是毫无意义的。

如何克服这个问题?一个学术上的答案是你可以使用专门的软件和硬件,比如实时操作系统,但是开发软件比定期编程要复杂得多。您可能真正想知道的是,在通常情况下,文档所指的延迟并不重要,即它通常少于1/100秒。

答案 2 :(得分:0)

使用暴力循环...例如:

chrono::microseconds sleep_duration{1000};

auto now = chrono::high_resolution_clock::now()

while(true)
{
    auto elapsed = chrono::duration_cast<hrono::microseconds>(chrono::high_resolution_clock::now() - now);
    if (elapsed > sleep_duration)
        break;
}

这有点难看,但桌面操作系统不是实时的,所以你不能有这么精确。

为了放松cpu,请查看以下代码段:

void little_sleep(std::chrono::microseconds us)
{
    auto start = std::chrono::high_resolution_clock::now();
    auto end = start + us;
    do {
        std::this_thread::yield();
    } while (std::chrono::high_resolution_clock::now() < end);
}

答案 3 :(得分:0)

这取决于您可以预期的准确度。一般情况下,其他人都说常规操作系统(Linux,Windows)无法保证。

<强>为什么吗
您的操作系统可能有线程概念。如果是这样,那么有一个调度程序会中断线程并将执行切换到队列中等待的其他线程。这会破坏计时器的准确性。

我该怎么办?

  1. 如果您使用的是嵌入式系统 - 请选择裸机,即不要使用 操作系统或使用所谓的硬实时操作系统。
  2. 如果您使用的是Linux,请在Google中查找Linux RT Preempt Patch。你必须重新编译你的内核以包含路径(虽然不是那么复杂)然后你可以创建优先级高于50的线程 - 这意味着优先于内核的线程 - 这最终意味着你可以拥有一个线程一般可以中断调度程序和内核,提供相当好的时间准确性。在我的情况下它是三个数量级(从几毫秒的延迟到几个我们)。
  3. 如果您使用的是Windows,我不了解此类补丁,但您可以在Microsoft网站上搜索High Precisions计时器。也许提供的准确性足以满足您的需求。