c3p0 を使用して、アプリケーションでのデータベース接続の作成と破棄をログに記録しようとしていますConnectionCustomizer
。その中に、次のようなコードがあります。
log(C3P0Registry.getPooledDataSources())
私はデッドロックに陥っています。c3p0 のライブラリには、同期メソッドを使用する少なくとも 2 つのオブジェクトがあり、意図したロック順序を指定していないようです。接続をログに記録すると、ロックがかかっていてC3P0Registry
、最終的にはPoolBackedDataSource
(単純にデータソースのリストを作成すると、ハッシュコードにアクセスしてロックが発生します)。
接続プロバイダーをシャットダウンする ( を呼び出すC3P0ConnectionProvider.close()
) と、ロックが逆の順序で呼び出されます。しかし、子データソースがシャットダウンされている間、ログがトリガーされています。その結果、デッドロックが発生します。
私がc3p0ライブラリに行っている呼び出しは両方とも有効で、予想される呼び出しのようです:
C3P0ConnectionProvider.close()
C3P0Registry.getPooledDataSources()
また、(ドキュメントに明示的に記載されていない限り)独自のロック戦略を管理するのはライブラリの責任であるように思われます。(これは誰かを責めるために言っているのではありません..ベストプラクティスについての私の理解を確認するためだけです)
この問題にどのように対処すればよいですか? c3p0 は最新のメカニズムではなく同期メソッドを使用しているため、実際にロックをテストすることはできません。
DataSource
クロージング コードから、最初にC3P0Registry
ロックを取得してからDataSource
. 私は正しいロック順序を推測していますが、それが快適かどうかはわかりません。
ロギング呼び出しのロック順序を逆にすることはできないと思います。C3P0Registry
のリストを取得するにはが必要なので、それらへの参照を取得するために最初にロックしDataSources
ないと をロックできませんでした。DataSources
C3P0Registry
もちろん、別の解決策は、すべての c3p0 の上に別のより高いレベルのロックを提供することです。接続プールの場合、それはポイントを無効にしているようです。
今のところ、ログをロールバックしています。助けてくれてありがとう。