Try-Lock 的背后理念

Try-Lock 的背后理念

文一

2024-10-22 发布56 浏览 · 1 点赞 · 0 收藏

Try-Lock 的背后理念

只有建立深刻理解,才可以把事情干成。只有抱持强烈欲望,方能够走向成功。我们将继续前进,为建成一个繁荣的数据库内核生态(存储引擎方面)而作出关键性的贡献。


在美团《基本功 | 一文讲清多线程和多线程同步》(https://tech.meituan.com/2024/07/19/multi-threading-and-multi-thread-synchronization.html)这篇文章之中,作者对于 “ABBA” 的死锁情况展开了讨论,文章指出:


ABBA 锁

假设程序中有2个资源X和Y,分别被锁A和B保护,线程1持有锁A后,想要访问资源Y,而访问资源Y之前需要申请锁B,而如果线程2正持有锁B,并想要访问资源X,为了访问资源X,所以线程2需要申请锁A。线程1和线程2分别持有锁A和B,并都希望申请对方持有的锁,因为线程申请对方持有的锁,得不到满足,所以便会陷入等待,也就没有机会释放自己持有的锁,对方执行流也就没有办法继续前进,导致相持不下,无限互等,进而死锁。

上述的情况似乎很明显,但如果代码量很大,有时候,这种死锁的逻辑不会这么浅显,它被复杂的调用逻辑所掩盖,但抽茧剥丝,最根本的逻辑就是上面描述的那样。这种情况叫ABBA锁,既某个线程持有A锁申请B锁,而另一个线程持有B锁申请A锁。这种情况可以通过try lock实现,尝试获取锁,如果不成功,则释放自己持有的锁,而不一根筋下去。另一种解法就是锁排序,对A/B两把锁的加锁操作,都遵从同样的顺序(比如先A后B),也能避免死锁。


ABBA

(我使用 draw.io 制作了一份动画,可以看到,ABBA 的实质就像稻盛和夫《活法》中所提及的地狱:“地狱里的人只想着争抢对方口中的面条,最后谁也没吃上”)

而最终解决的办法,也有着利他哲学的理念,即先尝试申请一份所需要的资源,如果申请不下来,就暂时先把自己手里的资源放出来,以免误了别人的事情(这就像天堂里面,我考虑你,你也考虑我)。

Try-Lock 的基本范式

使用伪代码表述如下:

have lock a, try lock b ...
if (lock b success) {
    do something ...
    free the lock a, b
}
else {
    free the lock a
    handle the error ...
}

写在最后

感谢美团的技术老师,感谢 KiwiDB 团队中 ohmhong 的帮助, 我们将继续前进,为建成一个繁荣的数据库内核生态(存储引擎方向)而作出贡献。