我寫了一個數據庫連接池,用於大型多線程應用程序,寫入目標jdk4標準,使用下面的代碼我可以在0.4秒內通過我的測試用例在局域網上查詢一個MySQL數據庫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爲空)等性能降低,使得它需要4秒鐘做歷時0.4秒相同的查詢。
爲什麼會出現這種情況?
編輯:
我已經解決了這一點,問題就出現了從創建太多連接時功能塊的方式。
這就是在函數開始時發生的事情。
synchronized(waitLocK) {
try {
while(count >= limit) {
waitLock.wait();
}
} catch (InterruptedException e) {
}
}
當連接被釋放時waitLock被釋放。但是這裏發生的是,在創建連接的代碼塊之後,計數變量(volatile)會增加。
這具有打開門的效果,因爲當1000個線程試圖通過等待測試時,他們都通過了,因爲count仍然爲0,然後重載了getConnection()。
移動count ++爲try後解決此問題。
c是一個全局變量嗎? – Tudor 2012-02-01 10:29:39
對不起,C是本地功能。 – FEiN 2012-02-01 10:35:35
「我正在寫一個數據庫連接池」......這是什麼?有幾種可以使用的開源軟件。這是一個難以解決的問題,不要重新發明輪子。 – skaffman 2012-02-01 10:38:36