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

How absl::Mutex's conditional critical sections handle reader wakeups

本文关键字:处理 读取 唤醒 何处理 Mutex 条件 键部 absl      更新时间:2023-10-16

我想知道最好问这样的事情,所以我在meta(https://meta.stackexchange.com/questions com/questions/304981)上问了这个问题指向这里,所以来了。

我真的很好奇Google使用absl::Mutex(https://github.com/abseil/abseil/abseil/abseil/abseil/blob/master/master/master/master/master/synchronization/mutex.h)内置了哪种优化。。特别是我想知道当读者的状况变为真时,他们如何处理读者唤醒。他们是否也唤醒等待清单中的所有其他读者?这条线似乎表示他们在做。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

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

通过查看他们的来源,Absl似乎并没有尝试魔术避免向待定的读者广播,因此,是的,雷鸣般的群体仍然是一个问题。通常,没有任何实施可以以有意义的方式解决该问题。这是一个设计问题。

通过将条件嵌入锁的一部分,ABSL:确实允许程序员避免或设计该问题。仍然有一个群,但是锁实现能够在此处点点头。如果您设计出唤醒良好的理由,例如在面具中钻头,则可以安全地使用共享/独家锁,而不必担心会影响您的性能的虚假唤醒。

这是"设计优化"的本质:该问题在源中更明确地描述了,而所得的实现比其他质量更高(性能,缩放,...)。

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

丑陋的问题是有一个:没有同时的东西,b:锁处理容易容易出错(我握住其他锁吗?这会导致僵局吗?),并且在程序中没有很好地表达。Plan9的睡眠和唤醒优雅地合并了这些,因此在检查病情的那一刻,任何人都不可能影响物体。实际上,引用论文的目的是执行该简单合同是多么困难。例如,最好避免使用多处理环境中的复杂合同。

关键优化(在ABSL中:)是不需要通过昂贵的上下文开关操作来确定对象处于错误状态,然后重新入睡。如果选择唤醒您的代码可以验证对象状态是您可能感兴趣的对象状态,那么越好。函数调用/方法调用比上下文开关快100倍。

absl 本节既介绍了如何选择唤醒的候选者,又介绍了如何剔除牛群。本节生成广播。

因此,前一节从列表服务员中选择元素,后一节将它们唤醒。如果您查看第2203行的其他条件,它显示了作者将如何终止列表 - w_walk-> Wake不正确,并且已经设置了WR_WAIT。此外,较早的测试在2015年和2023

MONITORS

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

要求此线程执行后卫条件。移动该阻挡线的动作可能是执行条件的成本的1000倍。相反:

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

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