我正在尝试使用 c3p0's 在我们的应用程序中记录数据库连接的创建和销毁ConnectionCustomizer
。在其中,我有一些看起来像这样的代码:
log(C3P0Registry.getPooledDataSources())
我遇到了僵局。我发现 c3p0 在其库中至少有几个使用同步方法的对象,并且似乎没有指定它们预期的锁定顺序。当我记录连接时,我会锁定C3P0Registry
并最终PoolBackedDataSource
(只需创建数据源列表即可访问导致锁定的哈希码)。
关闭连接提供程序(调用C3P0ConnectionProvider.close()
)会导致以相反的顺序调用锁。但是,当子数据源被关闭时,我的日志记录被触发了。结果是死锁。
似乎我对 c3p0 库进行的两个调用都是有效的预期调用:
C3P0ConnectionProvider.close()
C3P0Registry.getPooledDataSources()
似乎(除非在文档中明确说明)管理它自己的锁定策略应该是库的责任。(我说这不是为了责怪任何人.. 只是为了确认我对最佳实践的理解)
我应该如何处理这个问题?由于 c3p0 使用同步方法而不是更现代的机制,因此我无法真正测试锁。
从我的DataSource
关闭代码中,我可以C3P0Registry
在关闭DataSource
. 我会猜测正确的锁定顺序,我不知道我是否觉得舒服。
我不认为我可以反转日志调用的锁定顺序。我需要C3P0Registry
来获取 的列表DataSources
,所以如果DataSources
没有先锁定C3P0Registry
来获取对它们的引用,我就无法锁定 。
当然,另一种解决方案是在 c3p0 之上提供另一个更高级别的锁。在连接池的情况下,这似乎违背了这一点。
现在,我正在回滚我的日志记录。谢谢你的帮助。