Я пишу пул соединений с базой данных для использования в большом многопоточном приложении, написанном для целевых стандартов jdk4, с помощью следующего кода я могу запросить базу данных mysql по локальной сети 1000 раз за 0,4 секунды с помощью моего тестового примера.
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 секунды, занимает 4 секунды.
Почему это так?
РЕДАКТИРОВАТЬ:
Я решил эту проблему, проблема возникает из-за способа, которым функциональные блоки создаются при слишком большом количестве соединений.
Это то, что происходило в начале функции.
synchronized(waitLocK) {
try {
while(count >= limit) {
waitLock.wait();
}
} catch (InterruptedException e) {
}
}
waitLock освобождается при освобождении соединения.Но здесь происходит то, что после блока кода для создания соединения увеличивается переменная count (volatile).
Это привело к открытию шлюзов, потому что, когда 1000 потоков пытались пройти тест ожиданиявсе они прошли, потому что count был все еще 0, а затем перегружен getConnection ().
Перемещение count ++ на значение после попытки решает эту проблему.