如何在C++11中防止线程饥饿问题

12

我想知道C++11是否有锁定策略可以防止线程饥饿。

我有一堆线程竞争一个互斥量。现在,我的问题是离开临界区的线程立即开始竞争同一个互斥量,并大多数时候获胜。因此等待互斥量的其他线程就会挨饿。

我不想让离开临界区的线程休眠一段时间以给其他线程锁定互斥量的机会。

我认为必须有某个参数可以启用对等锁定,以使等待互斥量的线程公平锁定,但我无法找到任何适当的解决方案。

好吧,我发现了std::this_thread::yield()函数,它应该重新安排线程执行的顺序,但它只是调度程序线程的提示,取决于调度程序线程实现是否重新安排线程。

C++11中有没有提供公平锁定策略,以便在等待同一互斥量的线程之间提供公平性?

通常的策略是什么?

谢谢


1
这里有一个链接可能会对你有所帮助!https://dev59.com/zmgu5IYBdhLWcg3wASSO - William Proulx
这似乎是一个设计问题,而不是线程饥饿问题,请你发布代码让人们看到并提供帮助。 - dirvine
1
通常情况下,不应该有一堆线程竞争一个互斥锁--如果你的代码是如此串行化,只有一个线程可以同时工作,为什么不减少线程呢?虽然有合理的原因,但它们并不都是相同的合理原因,而且它们可能有不同的答案! - Yakk - Adam Nevraumont
我有一堆线程竞争一个互斥锁的原因是我正在尝试实现监视器设计模式来解决餐桌哲学家问题。也就是说,所有操作共享数据的方法都通过监视器公共方法进行同步。每个公共方法在开始时锁定互斥锁,检查是否可以继续执行,如果不能,则挂起并等待条件变量。 - Tomas Sedlacek
1个回答

8
这是一种常见的互斥锁优化,旨在避免当同一线程可以再次获取互斥锁时浪费时间切换任务。如果当前线程在其时间片中仍有剩余时间,则通过让它获取互斥锁而不是挂起它并切换到另一个线程(这可能会导致缓存行和各种其他延迟的大量重新加载),从而获得更高的每秒执行用户指令的吞吐量。
如果您的互斥锁存在如此多的竞争,以至于这成为问题,则您的应用程序设计是错误的。您所有这些线程都被阻塞在互斥锁上,因此什么也没做:您可能最好减少这么多线程。
您应该设计您的应用程序,以便如果多个线程竞争互斥锁,则无论哪个线程获得锁都没有关系。直接竞争也应该是罕见的,尤其是具有大量线程的直接竞争。
我能想到这种情况下唯一可以接受的方案是每个线程都在等待条件变量,然后广播以唤醒它们所有人。然后每个线程将争夺互斥锁,但是如果您做得对,则它们都应该快速检查这不是虚假唤醒,然后释放互斥锁。即使在这种情况下,这也被称为“雷鸣般的群体”情况,而且并不理想,因为它会串行化所有这些线程。

有时候设计不是你自己的,承认设计不好并不能神奇地解决问题。我来到这里是因为我正在尝试解决 mic offload 库中的线程饥饿问题。出于某种原因,作者假定保护共享资源即使对于使用单个互斥锁的多个设备也是可以的。 - Jacek Tomaka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接