Если вы знаете, что конкретный поток является последним потоком для запроса конкретной блокировки, вы можете просто использовать locks.remove(id, id)
. В противном случае вам понадобится атомное обновление для двух событий, которые не могут быть легко синхронизированы вместе.
Если вы отпустите и затем удалите блокировку, другой поток может захватить блокировку, которую вы выпустили, а дополнительный поток делает новый объект блокировки незаметным для исходного объекта блокировки. В этой ситуации вы можете получить два потока, вызывающих getFromDataBase(id)
или cache.store(p)
одновременно. Если вы удалите и затем отпустите вместо этого, у вас может быть другой поток, ожидающий, когда вы отпустите старый замок, в то время как новый поток уже сделал новую блокировку. Такое же столкновение может произойти.
По существу, вы не можете атомизировать блокировку и удалить ее из HashMap без добавления новой блокировки в систему. В этом случае вы либо получаете глобальную блокировку, которая побеждает ускорение специфической блокировки хэша, либо вам нужна дополнительная блокировка для каждой страницы, которая сама будет иметь те же проблемы с удалением. В качестве альтернативы, если у вас есть доступ к внутренним компонентам HashMap, вы можете попробовать какую-то сложную блокировку блокировки ведра для своей логики более высокого уровня, хотя я бы не рекомендовал пытаться реализовать такую вещь.
Одним из решений для ограничения размера хэш-карты является использование сопоставления с фиксированным размером. Измените идентификатор Integer с большим числом (10 000) и используйте модифицированный номер как уникальный идентификатор блокировки. Вероятность столкновения двух хешей и требование одинаковой блокировки для разных страниц была бы очень маленькой, и у вас была бы жесткая кепка на памяти, потребляемой замками. В этом случае вам действительно не нужен HashMap, поскольку вы могли предварительно выделить объекты блокировки Integer в статический массив констант и запросить хэш-код мод непосредственно из объектов id.
Также вы должны быть осторожны, чтобы кеш читался за пределами блокировки, если только сам кеш не защищен от одновременной чтения-записи, поскольку поток может писать, в то время как другой считывает с того, как код указан в вопросе.
И в чем проблема с 'locks.remove (id, id)'? – OldCurmudgeon
Карта блокировки будет меньше, чем фактический кеш. Есть ли механизм для очистки кеша? Если это так, возможно, необходимо очистить карту блокировки. – flup