大きなマルチスレッドアプリケーションで使用するためのデータベース接続プールを作成して、次のコードでjdk4標準をターゲットにして作成しました。テストケースでLAN経由でmysqlデータベースを0.4秒で1000回クエリできます。ここでこのロックの変更は、JDBCのパフォーマンスに大きな影響を与えるのはなぜですか?
synchronized(lockA) {
if(free.size() > 0) {
c = (Connection) free.removeFirst();
}
if(c == null) {
c = DriverManager.getConnection(query, name, passw);
}
}
LOCKAは、リストが変更され、アクセスされた場合、それが使用される、フリーリスト(LinkedListの)を保護します。 getConnectionをこのロックから自分自身の保護ブロックに移動することは理にかなっていました。 getConnectionは、スレッドセーフではないため、ロックによって保護する必要があります。
私はそれを変更すると、DriverManagerとリストは別々のロックで保護されます。
synchronized(lockA) {
if(free.size() > 0) {
c = (Connection) free.removeFirst();
}
}
if(c == null) {
synchronized(lockB) {
c = DriverManager.getConnection(query, name, passw);
}
}
私は連続したキャッシュミス(Cがヌル)になり、パフォーマンスが低下し、同じクエリを実行するのに0.4秒かかってしまいます。
これはなぜですか?
EDIT:
私はあまりにも多くの接続を作成するときに問題が途中から機能ブロックを生じ、これを解決しました。
これは、機能の開始時に起こったことです。
synchronized(waitLocK) {
try {
while(count >= limit) {
waitLock.wait();
}
} catch (InterruptedException e) {
}
}
接続が解除されると、waitLockが解放されます。しかし、ここで起こっているのは、接続を作成するコードブロックの後で、カウント変数(volatile)がインクリメントされるということです。
これは、1000スレッドが待機テストを通過しようとしたときにカウントがまだ0だったためにすべて通過し、getConnection()がオーバーロードされたためです。
試行後にカウント++を移動すると、この問題が解決されます。
'c'はグローバル変数ですか? – Tudor
申し訳ありません。Cは、この関数のローカルです。 – FEiN
「データベース接続プールを作成しています」....何のために?あなたが使用できるいくつかのオープンソースのものがあります。解決するのは難しい問題ですが、ホイールを再構築しないでください。 – skaffman