C ++ 11 sleep_函数具有奇怪的行为

时间:2014-04-04 12:58:57

标签: c++ gcc c++11

Here它表示sleep_for"阻止执行的当前线程至少指定的sleep_duration。"

Here它表示sleep_until"阻止当前线程的执行,直到达到指定的 sleep_time 。&# 34;

所以考虑到这一点,我只是在做我的事情,直到我注意到我的代码比指定的时间要短得多。为了确保睡眠代码是奇数而不是我再次制作哑码,我创建了这个在线示例:https://ideone.com/9a9MrC (编辑行下面的代码块)当运行在线示例时,它完全按照它应该做的那样,但在我的机器上运行完全相同的代码示例给出了这个输出:Output on Pastebin

现在我真的很困惑,想知道我的机器上哔哔出了什么问题。我在Win7 x64机器上使用Code :: Blocks作为IDE,并与包含GCC 4.8.2的This工具链结合使用。

*我在当前版本之前尝试了This工具链,但是这个奇怪的GCC 4.8.0甚至无法编译示例代码。

什么可能造成这种奇怪的行为?我的机器?视窗? GCC?工具链中的其他东西?

P.S。该示例也适用于Here,它表明它使用GCC版本4.7.2

p.p.s。使用#include <windows.h>Sleep( 1 );的时间也比我机器上指定的1毫秒短很多。

编辑:示例中的代码:

#include <iostream>         // std::cout, std::fixed
#include <iomanip>          // std::setprecision
//#include <string>           // std::string
#include <chrono> // C++11  // std::chrono::steady_clock
#include <thread> // C++11  // std::this_thread

std::chrono::steady_clock timer;
auto startTime = timer.now();
auto endTime = timer.now();
auto sleepUntilTime = timer.now();

int main() {

for( int i = 0; i < 10; ++i ) {
    startTime = timer.now();
    sleepUntilTime = startTime + std::chrono::nanoseconds( 1000000 );
    std::this_thread::sleep_until( sleepUntilTime );
    endTime = timer.now();
    std::cout << "Start time: " << std::chrono::duration_cast<std::chrono::nanoseconds>( startTime.time_since_epoch() ).count() << "\n";
    std::cout << "End   time: " << std::chrono::duration_cast<std::chrono::nanoseconds>( endTime.time_since_epoch() ).count() << "\n";
    std::cout << "Sleep till: " << std::chrono::duration_cast<std::chrono::nanoseconds>( sleepUntilTime.time_since_epoch() ).count() << "\n";

    std::cout << "It took: " << std::chrono::duration_cast<std::chrono::nanoseconds>( endTime - startTime ).count() << " nanoseconds. \n";
    std::streamsize prec = std::cout.precision();
    std::cout << std::fixed << std::setprecision(9);
    std::cout << "It took: " << ( (float) std::chrono::duration_cast<std::chrono::nanoseconds>( endTime - startTime ).count() / 1000000 ) << " milliseconds. \n";
    std::cout << std::setprecision( prec );
}
std::cout << "\n\n";
for( int i = 0; i < 10; ++i ) {
    startTime = timer.now();
    std::this_thread::sleep_for( std::chrono::nanoseconds( 1000000 ) );
    endTime = timer.now();
    std::cout << "Start time: " << std::chrono::duration_cast<std::chrono::nanoseconds>( startTime.time_since_epoch() ).count() << "\n";
    std::cout << "End   time: " << std::chrono::duration_cast<std::chrono::nanoseconds>( endTime.time_since_epoch() ).count() << "\n";

    std::cout << "It took: " << std::chrono::duration_cast<std::chrono::nanoseconds>( endTime - startTime ).count() << " nanoseconds. \n";
    std::streamsize prec = std::cout.precision();
    std::cout << std::fixed << std::setprecision(9);
    std::cout << "It took: " << ( (float) std::chrono::duration_cast<std::chrono::nanoseconds>( endTime - startTime ).count() / 1000000 ) << " milliseconds. \n";
    std::cout << std::setprecision( prec );
}

return 0;
}

1 个答案:

答案 0 :(得分:2)

您的机器没有任何问题,这是您错误的假设。

睡眠是一个非常依赖系统和不可靠的事情。通常,在大多数操作系统上,您或多或少地保证睡眠调用将延迟执行至少您要求的时间。 C ++线程库必然使用操作系统提供的功能,因此引用了C ++标准中的措辞。

您将在上一段中注明“或多或少保证”的措辞。首先,睡觉的方式不是你想象的那样。它通常不会阻塞,直到计时器触发然后恢复执行。相反,它只是将线程标记为“未准备好”,并且另外执行某些操作以便稍后可以撤消(这究竟是什么未定义,可能是设置计时器或其他内容)。 时间到了,操作系统会将线程再次设置为“准备运行”。这并不意味着它会运行,它只意味着它是一个运行的候选者,只要操作系统可以被打扰,并且只要CPU核心是空闲的(并且具有更高优先级的nobobdy想要它)。

在传统的非无滴答操作系统上,这意味着线程可能(或更确切地说,可能)在下一个调度程序时刻运行。也就是说,如果CPU可用的话。在更“现代化”的操作系统(Linux 3.x或Windows 8)上,您可以更接近现实,但您仍然没有任何硬性保证。

此外,在类Unix系统中,sleep可能会被信号中断,实际上可能会等待少于指定的时间。此外,在Windows下,调度程序运行的时间间隔是可配置的,更糟糕​​的是,不同的Windows版本在处理睡眠时间是向上还是向下时表现不同[1] [2]。登记/> 您的系统(Windows 7)向向下,所以确实是的,您实际上可能等待的时间少于预期。

TL;博士

睡眠是不可靠的,只是一个非常粗略的“提示”(非要求),您希望将控制权传递回操作系统一段时间。