640просмотров
30.2%от подписчиков
10 февраля 2026 г.
Score: 704
🐢 Ваш by lazy тормозит (и вы об этом не знаете) Мы привыкли писать так: val formatter by lazy { expensiveInitialization() } Это стандарт де-факто для тяжелых объектов.
Но знаете ли вы, что по умолчанию lazy использует режим LazyThreadSafetyMode.SYNCHRONIZED? Что это значит под капотом:
Каждое обращение к переменной (даже после того, как она инициализирована!) проходит через проверку volatile поля. А при первой инициализации создается монитор (lock), чтобы гарантировать потокобезопасность. Double-checked locking это надежно, но это оверхед. Сценарий 1: Android Main Thread
Если вы используете by lazy внутри Activity или Fragment для инициализации View-компонентов или адаптеров, вы зря тратите такты процессора на синхронизацию. UI-поток один. Конкуренции нет. Зачем платить за лок? Сценарий 2: Backend Request Scope
Если объект живет в рамках одного запроса, который обрабатывается одним потоком, синхронизация там тоже лишняя. 🚀 Решение: Если вы уверены, что к переменной обращается только один поток (например, Main Thread), используйте: val formatter by lazy(LazyThreadSafetyMode.NONE) { expensiveInitialization() } Результат: • Никаких synchronized блоков.
• Никаких volatile чтений.
• Чистая проверка if (value != UNINITIALIZED_VALUE). ⚡️ Бенчмарки:
На горячих путях (hot path), где к проперти обращаются тысячи раз в секунду, mode = NONE работает быстрее на ~15-20% за счет отсутствия memory barriers. Третий режим:
Есть еще PUBLICATION. Это когда несколько потоков могут попытаться инициализировать значение одновременно, но победит тот, кто первый запишет. Остальные вычисления будут отброшены. Полезно, если лок стоит дороже, чем повторное вычисление. Признавайтесь, кто пишет LazyThreadSafetyMode.NONE, а кто оставляет дефолт "на всякий случай"? 👇 ✍️ @kotlin_lib