absl :: Mutex的条件关键部分如何处理读取器唤醒

问题描述 投票:10回答:1

我想知道最好问一下这样的事情,所以我在Meta(https://meta.stackexchange.com/questions/304981)上问了这个问题并且被引导到这里,所以这里就是这样。

我真的很好奇Google使用absl::Mutexhttps://github.com/abseil/abseil-cpp/blob/master/absl/synchronization/mutex.h)实现条件关键部分的实现有哪些优化。特别是我想知道当读者的情况变为现实时他们如何处理读者唤醒。他们是否也在等候名单中唤醒所有其他读者? This line似乎表示他们确实这样做了。这不是每次都有O(n)遍历的风险,并且还会冒着写优先级互斥体的风险吗?

c++ multithreading synchronization mutex
1个回答
4
投票

我认为设置设计和实现优化之间的差异非常重要。似乎absl ::通过提供支持这些设计的实现来优先考虑更好的设计,而不是提供更好的优化组件。有时,更好的设计本质上比笨拙的设计表现更好,因此结果在两个因素(协同作用)上得到优化。 Absiel.io更详细地讨论了这一点。

从他们的消息来源来看,绝对不会尝试魔术来避免向未决的读者广播,因此是的,雷鸣般的群体仍然是一个问题。一般而言,任何实施都无法以有意义的方式解决该问题;这是一个设计问题。

通过将条件作为锁的一部分嵌入,absl:允许程序员避免或设计该问题。还有一个群,但锁实现能够瘦它 plan 9 nod here 。如果你设计好觉醒的原因,例如掩码中的位,你可以安全地使用共享/独占锁,而不必担心会影响你的性能的虚假唤醒。

这是“设计优化”的本质:问题在源中更明确地描述,并且所得到的实现具有比其他方式更高的质量(性能,缩放......)。

Plan9相关。条件变量等同于unix内核的睡眠概念(不是时间一)和唤醒。当您检测到某个对象未处于您需要的状态时,您会执行一些操作以启动将其置于该状态,然后等待直到达到该状态。例如,您可以在缓存中查找对象,并在发现它不存在时,创建一个无效的对象并请求它变为有效。这允许所有缓存参与者之间的一种对称:它们锁定对象,评估或更新其状态,然后同时解锁对象并等待对其进行进一步的更改。

丑陋的问题是存在:没有同时发生的事情,而且b:锁定处理容易出错(我是否持有任何其他锁?这会导致死锁吗?)并且在程序中没有很好地表达。 Plan9的睡眠和唤醒优雅地融合了这些,因此在检查条件时,任何人都不可能影响对象。事实上,参考文献的重点是执行这份简单合同有多难。 for example最好避免在多处理环境中复杂的合同。

关键优化(在绝对:)是没有必要通过昂贵的上下文切换操作来确定对象处于错误状态,然后再回到睡眠状态。如果选择唤醒你的代码可以验证对象状态是你可能感兴趣的那个,那就更好了。函数调用/方法调用比上下文切换快100倍。

Absl This section解决了如何选择唤醒候选人以及如何剔除牧群的问题。 This section制作广播节目。

因此前一部分从列表服务员中选择元素,后一部分将其唤醒。如果查看第2203行的其他条件,它会显示编写器将如何终止列表 - w_walk-> wake不成立,并且已设置wr_wait。此外,2015年和2023年的早期测试会阻止构建此列表,如果它是写入唤醒。

显示器

obj.enter();
while (obj.state != StateIWant) {
    obj.wait();
}
...
obj.exit();

需要此线程执行保护条件。移动该阻塞线程的动作可能是执行条件的成本的1000倍。相反:

obj.wait(^{return obj.state == StateIWant;});
...
obj.exit();

允许等待调用在允许等待的任何线程(即调用退出)的上下文中评估条件,从而避免在无用情况下的昂贵的上下文切换。

© www.soinside.com 2019 - 2024. All rights reserved.