我相信这是一种比赛条件,尽管非常罕见。具有持续时间的 condition_variable::timed_wait() 的实现只是使用 get_system_time()+wait_duration 将值转换为 system_time。如果系统时间在调用 get_system_time() 之间发生变化,并且计算出的等待结束时间被重新转换为底层操作系统调用的基于滴答的计数器,那么您的等待时间将是错误的。
为了测试这个想法,在 Windows 上,我编写了一个简单的程序,其中一个线程每 100 毫秒生成一些输出,如下所示:
for (;;)
{
boost::this_thread::sleep( boost::get_system_time() +
boost::posix_time::milliseconds( 100 ) );
std::cout << "Ping!" << std::endl;
}
另一个线程每 100 毫秒将系统时间设置回过去一分钟(该线程使用操作系统级别的“Sleep()”调用来避免转换为系统时间):
for ( ;; )
{
Sleep( 100 );
SYSTEMTIME sysTime;
GetSystemTime( &sysTime );
FILETIME fileTime;
SystemTimeToFileTime( &sysTime, /*out*/&fileTime );
ULARGE_INTEGER fileTime64 = (ULARGE_INTEGER(fileTime.dwHighDateTime) << 32) |
fileTime.dwLowDateTime;
fileTime64 -= 10000000 * 60; // one minute in the past
fileTime.dwHighDateTime = (fileTime64>>32) & 0xFFFFFFFF;
fileTime.dwLowDateTime = fileTime64 & 0xFFFFFFFF;
FileTimeToSystemTime( &fileTime, /*out*/&sysTime );
SetSystemTime( &sysTime );
}
第一个线程,虽然应该输出“Ping!” 每 100 毫秒,相当快地锁定。
除非我遗漏了什么,否则 Boost 似乎没有提供任何 API 来避免内部转换为系统时间的问题,从而使应用程序容易受到外部时钟更改的影响。