1

我和同事讨论了一个假设的问题,当一个人想要用 实现自旋锁互斥锁std::atomic_flag,但也不是将自旋锁实现为 while(true) 而是作为

while(true)
{
     cnt=0;
     while (cnt<yieldAfterTries)
     {
        //try to get lock
        cnt++;
     }
     std::this_thread::yield();

     // if got lock do work and then break;
}     

基本上的想法是,即使它具有实时优先级,线程也不能“在很长时间内”阻塞其他线程,因为它会在一段时间后产生......但是当我看到 std::yield 的规范时,我很惊讶它是一个建议,不是强制性的。

为实现提供提示以重新安排线程的执行,从而允许其他线程运行。

http://en.cppreference.com/w/cpp/thread/yield

那会不会有问题?

4

2 回答 2

6

我编写的代码与您的代码非常相似,并测量了yield在高争用条件下调用的影响。我发现yield以这种方式使用有益于整个系统的吞吐量。

实际规范与您引用的内容在精神上没有什么不同,但这里是 30.3.2 [thread.thread.this] 第 2 和第 3 段的确切规范:

void this_thread::yield() noexcept;

效果:为实施提供重新安排的机会。

同步:无。

如果实现实现yield为无操作(例如),这将仅影响代码的性能,而不影响正确性。即使没有yield. 但它也更有可能不必要地占用 CPU,从而降低整体系统性能。

于 2013-01-18T17:38:10.347 回答
1

操作系统调度程序将自动抢占自旋锁,从而使此代码变得不必要。当一个线程占用了它的时间时,操作系统将自动切换到另一个线程。这就是为什么 yield 是一个提示。例如,在 Linux 中的完全公平调度中,对 yield 的调用通常会导致不必要的上下文切换,因为调度试图纠正一个线程没有得到公平的时间份额。

您尝试获取自旋锁不会阻塞任何东西,只有持有自旋锁会导致其他事物阻塞。

于 2013-01-18T15:49:10.320 回答