Питання 22 · Розділ 13

В чому перевага незмінних об'єктів для кешування?

Незмінні об'єкти ідеально підходять для кешування, тому що їх вміст не змінюється.

Мовні версії: English Russian Ukrainian

Junior Level

Незмінні об’єкти ідеально підходять для кешування, тому що їх вміст не змінюється.

Переваги

  1. Безпечне повернення — можна віддавати об’єкт з кешу напряму, не роблячи копію
  2. Стабільні ключіhashCode не змінюється, об’єкт не “загубиться” в кеші
  3. Багатопотоковий доступ — кілька потоків можуть читати кеш одночасно без блокувань

Приклад

// Незмінний об'єкт — можна кешувати безпечно
public record Product(String id, String name, BigDecimal price) {}

Map<String, Product> cache = new ConcurrentHashMap<>();
cache.put("1", new Product("1", "Book", new BigDecimal("9.99")));

Product p = cache.get("1"); // безпечно — ніхто не змінить p

Middle Level

Стабільність ключа кешу

Якщо об’єкт — ключ у кеші (HashMap, Caffeine, Redis):

  • Його hashCode() має бути консістентним
  • Для незмінного об’єкта хеш обчислюється один раз і не змінюється
  • Ризик із мутабельним ключем: об’єкт зміниться і “загубиться” в іншому бакеті → витік пам’яті

Безпека при читанні (Read-sharing)

Незмінні значення можна повертати з кешу за посиланням:

  • Не потрібна захисна копія при кожному запиті
  • Безліч потоків працюють з одним екземпляром без блокувань
  • Без блокувань потоки не чекають монітори — немає context switch, немає park/unpark. На read-heavy навантаженні це дає лінійне масштабування з ростом числа ядер.

Патерн Flyweight

Незмінність дозволяє перевикористовувати об’єкти:

  • String Pool — кеш рядкових літералів
  • Integer Cache — числа від -128 до 127
  • Один екземпляр для всіх однакових значень

Відсутність “отруєння” кешу

З мутабельним об’єктом один потік може отримати об’єкт і змінити його — це “отруїть” кеш для всіх. Незмінність гарантує, що дані залишаються в первозданному вигляді.


Senior Level

Ефективність для GC

Незмінні об’єкти в кеші потрапляють в Old Generation. Оскільки вони не змінюються, незмінні об’єкти після створення не породжують нових cross-generation посилань, що спрощує роботу GC при скануванні Old Generation.

Розподілене кешування

В Redis / Memcached:

  • Незмінні DTO безпечно серіалізуються/десеріалізуються
  • Немає ризику, що об’єкт зміниться під час серіалізації
  • Ідеально для CQRS / Event Sourcing

Резюме для Senior

  • Незмінність — ключ до Lock-free доступу до кешу
  • Запобігає псуванню даних через побічні ефекти
  • Детермінована робота з ключами
  • Використання незмінних DTO та Records — найкраща практика для систем кешування
  • Незмінні об’єкти не породжують cross-generation посилань, спрощуючи роботу GC

Шпаргалка для інтерв’ю

Обов’язково знати:

  • Безпечне повернення з кешу — можна віддавати за посиланням, не роблячи копію
  • Стабільні ключі — hashCode не змінюється, об’єкт не “загубиться” в бакеті
  • Lock-free багатопотоковий доступ — немає блокувань, немає context switch
  • Патерн Flyweight — перевикористання однакових об’єктів (String Pool, Integer Cache)
  • Відсутність “отруєння” кешу — один потік не може змінити об’єкт для всіх
  • GC efficiency — немає cross-generation посилань, спрощується сканування Old Generation

Часті уточнювальні запитання:

  • Чому мутабельний ключ небезпечний в кеші? — Зміниться hashCode → об’єкт “загубиться” → витік пам’яті
  • Чи потрібна defensive copy при поверненні з кешу? — Ні, незмінний об’єкт можна повернути за посиланням
  • Як незмінність допомагає розподіленому кешуванню? — Безпечна серіалізація, немає ризику зміни під час серіалізації
  • Що таке “отруєння” кешу? — Один потік отримує об’єкт і змінює його — “отруює” для всіх інших

Червоні прапорці (НЕ говорити):

  • «Незмінні об’єкти не можна кешувати» — вони ІДЕАЛЬНІ для кешування
  • «Потрібна синхронізація для читання кешу з незмінними об’єктами» — lock-free доступ
  • «Мутабельний ключ в HashMap — нормально» — при зміні об’єкт загубиться
  • «Кеш завжди повинен копіювати об’єкти» — для незмінних це зайве

Пов’язані теми:

  • [[2. Які переваги дає використання незмінних об’єктів]]
  • [[23. Як незмінність впливає на продуктивність]]
  • [[27. Чи можна використовувати незмінні об’єкти як ключі в HashMap]]
  • [[28. Що станеться, якщо змінити змінний ключ в HashMap]]