首页 > 解决方案 > 在这种情况下来自 Nygard 的“释放它!” 为什么会发生死锁?

问题描述

我一遍又一遍地阅读 Michael Nygard 的书“释放它!”中的这一段。而且我仍然不明白为什么会发生死锁:

想象一下 100,000 个事务都试图更新同一个数据库中同一个表的同一行。有人注定会陷入僵局。一旦锁定了用户配置文件的单个事务被挂起(因为需要来自不同资源池的连接),该行上的所有其他数据库事务都会被阻止。很快,每一个请求处理线程都被这些虚假登录用完了。一旦发生这种情况,该网站就关闭了。

当他说“因为需要来自不同资源池的连接”时,这是在数据库引擎内部吗?这个其他资源池是什么,为什么需要来自这个其他资源池的连接?

那么,“每个请求处理线程”已经不是指数据库线程,而是指应用程序线程,对吧?他们挂起是因为他们正在等待数据库事务(已经挂起)完成?

标签: threadpooldeadlockconnection-poolingdatabase-performancedatabase-deadlocks

解决方案


问题在于应用程序与许多不同的系统接口,其中任何一个系统都可以并行运行,具有内部或外部锁,并且依赖于更多系统。

一个简单的死锁示例基本上是当两个进程需要同时获取完全相同的两个锁才能继续进行时,但不能同意谁先去以及按什么顺序(这通常是锁的用途)首先,所以这是一个先有鸡还是先有蛋的问题,并不完全是微不足道的)。因此进程 A 和 B 需要获取两个锁 #1 和 #2 来完成它们的工作并继续。但是当 A 锁定 #1 时,B 锁定 #2,然后 A 尝试锁定 #2,B 尝试锁定 #1 -这是一个死锁。有人必须为任何工作做出让步。

在现实生活中,假设您正在运行 Web 应用程序的多个实例,以便能够同时处理多个传入的客户端请求(例如 Web 浏览器)。这些是线程、进程还是协程都没有关系。如果您的应用程序实例需要锁定两个数据库行,它们可能会挂起。或者它们可以挂起,因为除了数据库锁之外,它们还需要对文件系统中的文件进行锁。或者他们可以挂起,因为他们需要锁定文件系统中的文件,并且他们正在使用第三方远程 REST API,该 API 也有自己的锁定。或者由于无限的其他原因,同时包括上述所有原因。


推荐阅读