在写入Microsoft专用C++代码时,spinlocking时使用Sleep(1)比Sleep(0)好,是因为Sleep(0)将使用更多的CPU时间,而且Sleep(0)只有在有另外一个等于-priority线程等待运行。
然而,使用C++ 11线程库,没有太多关于std :: this_thread :: yield()与std :: this_thread :: sleep_for(至少可以找到)的文档std :: chrono :: milliseconds(1));第二个肯定是更冗长,但是它们对于自旋锁同样有效,还是会受到潜在的同样的影响睡眠(0)与睡眠(1)的感染?
一个示例循环,其中std :: this_thread :: yield()或std :: this_thread :: sleep_for(std :: chrono :: milliseconds(1))将是可以接受的:
void SpinLock( const bool& bSomeCondition )
{
// Wait for some condition to be satisfied
while( !bSomeCondition )
{
/*Either std::this_thread::yield() or
std::this_thread::sleep_for( std::chrono::milliseconds(1) )
is acceptable here.*/
}
// Do something!
}
最佳答案:
> yield将放弃当前时间片,并将线程重新插入到调度队列中。线程再次执行之前到期的时间通常完全取决于调度程序。请注意,标准将收益率称为重新安排的机会。所以一个实现是完全可以自由地从产量立即返回,如果它的愿望。收益率将永远不会将线程标记为非活动状态,因此产生收益的线程将始终在一个核心上产生100%的负载。如果没有其他线程已经准备就绪,则在重新安排计划之前,您最多可能会丢失当前时间片的剩余部分。
> sleep_ *将阻塞线程至少要求的时间量。一个实现可能会将sleep_for(0)转换成yield。另一方面,sleep_for(1)会让你的线程暂停。线程首先转到不同的睡眠线程队列,而不是返回到调度队列。只有在所请求的时间量过去之后,调度器才会考虑将线程重新插入到调度队列中。小睡眠所产生的负担仍将非常高。如果所请求的休眠时间小于系统时间片,您可以期望该线程只能跳过一次(即,一个产量释放活动时间片,然后跳过该时间片),这仍然会导致cpu加载在一个核心上接近或甚至等于100%。
另外:
C++11 标准库提供了yield()和sleep_for()两个方法。
(1)std::this_thread::yield(): 线程调用该方法时,主动让出CPU,并且不参与CPU的本次调度,从而让其他线程有机会运行。在后续的调度周期里再参与CPU调度。这是主动放弃CPU的方法接口。
(2)std::sleep_for():线程调用该方法时,同样会让出CPU,并且休眠一段时间,从而让其他线程有机会运行。等到休眠结束时,才参与CPU调度。这也是主动放弃CPU的方法。
两者的不同很明显:
1、yield()方法让出CPU的时间是不确定的,并且以CPU调度时间片为单位。而sleep_for()让出CPU的时间是固定的。
2、yield()的实现依赖于操作系统CPU调度策略,在不同的操作系统或者同一个操作系统的不同调度策略下,表现也可能是不同的。