The boost documentation for upgradable and shared locks表示当持有共享锁时,只有一个其他线程可能获得可升级的锁。因此,如果其他线程尝试获取可升级锁,当共享锁与可升级锁一起保存时,它们将阻止。
当多个线程获得可升级的锁以及一个(或多个共享锁)时,是否存在一些我失踪的死锁可能性?或者这只是一个逻辑要求(所以“不应该这样做”)?
请注意,我不是在谈论完全锁定状态。只有可升级的锁定状态。如果可升级锁与其他共享锁一起保存,则它本质上是一个READ锁。那么为什么两个可升级的锁不能连在一起呢?
答案 0 :(得分:4)
当多个线程获得可升级的锁时,是否存在一些我失踪的死锁可能性
TL; DR是的,有。
以及一个(或多个共享锁)
这并不会真正影响死锁的可能性。与独占锁相比,允许可升级锁存在时的共享锁只是可升级锁的一项功能。
让我们首先考虑可以使用哪些可升级锁。我们将想象以下情况:
现在,让我们考虑一下我们只有读取器(共享)/编写器(独占)锁,没有可升级的锁:
检查 - 写入周期的读取部分甚至阻止读取线程可能被认为是一个缺点。那么,让我们考虑一个替代方案:
在3和4之间。不止一个作家可能已经完成了对状态的检查 - 因为他们可以同时检查 - 并且现在正在争夺独占锁。只有一个可以赢,其他人必须阻止。当他们阻止时,获胜者正在改变状态。
在这种情况下,等待获取独占锁的编写者不能认为他们检查的条件已经有效了!另一位作家可能已经抓住了他们之前的锁,现在状态已被修改。他们可以忽略这一点,这可能会导致未定义的行为,具体取决于与条件和修改的关系。或者,当他们获得独占锁时,他们可以再次检查条件,这将使我们恢复到第一种方法,除非由于种族而可能无效的检查是无用的。无论哪种方式,这种方法都比第一种更差。
上述情况的解决方案是特权读取(可升级)锁定:
让我们考虑一下多个编写者被授予特权锁的情况。他们同时检查昂贵的情况,这很好,但他们仍然有竞争升级锁。这次,比赛导致死锁,因为每个编写者都持有读锁,并等待所有读锁在升级之前被释放。
如果可升级锁是与其他可升级锁相关的独占锁,则不会发生此死锁,并且在昂贵的检查和修改之间不存在竞争,但读取器线程仍然可以在写入器时运行检查。