[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-mnogopotochnost-nazovite-razlichiya-mezhdu-synchronized-i-reentrantlock":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":20,"progress":21,"seo":22},275,"nazovite-razlichiya-mezhdu-synchronized-i-reentrantlock",8,"mnogopotochnost","Многопоточность","🔀","Назовите различия между synchronized и ReentrantLock","\u003C!-- grade: 4\u002F5 — корректно, но объяснение реентрабельности можно сделать понятнее; расширены таблица и примеры -->\n\nВ Java 5 появился интерфейс `Lock`, а с ним — класс `ReentrantLock`, который предоставляет те же базовые возможности, что и ключевое слово `synchronized`, но дополняет их более тонким контролем над блокировкой.\n\n**Что такое реентрабельность (reentrant).** И `synchronized`, и `ReentrantLock` являются реентрабельными: если поток уже владеет блокировкой и повторно пытается её захватить, ему это позволяется. Внутри ведётся счётчик захватов — блокировка освободится только когда счётчик вернётся к нулю. Например:\n\n```java\n\u002F\u002F synchronized — реентрабельность встроена\nsynchronized (lock) {\n    synchronized (lock) { \u002F\u002F Повторный захват того же монитора — ОК\n        \u002F\u002F работаем\n    } \u002F\u002F счётчик -1\n} \u002F\u002F счётчик = 0, блокировка освобождена\n\n\u002F\u002F ReentrantLock — то же поведение\nReentrantLock lock = new ReentrantLock();\nlock.lock();   \u002F\u002F счётчик = 1\nlock.lock();   \u002F\u002F счётчик = 2\nlock.unlock(); \u002F\u002F счётчик = 1\nlock.unlock(); \u002F\u002F счётчик = 0, блокировка освобождена\n```\n\n**Сравнительная таблица:**\n\n| Характеристика | `synchronized` | `ReentrantLock` |\n|---|---|---|\n| Синтаксис | Ключевое слово языка | Явный объект `Lock` |\n| Освобождение | Автоматическое при выходе из блока | Ручное — обязательно в `finally` |\n| Прерываемое ожидание | Нет | `lockInterruptibly()` |\n| Попытка захвата без блокировки | Нет | `tryLock()` |\n| Попытка захвата с таймаутом | Нет | `tryLock(time, unit)` |\n| Политика честности (fairness) | Нет (зависит от JVM) | Да — `new ReentrantLock(true)` |\n| Условия ожидания (`Condition`) | Один набор (`wait`\u002F`notify`) | Множество `Condition` через `newCondition()` |\n| Производительность при высокой конкуренции | Хорошая (после оптимизаций JDK 6+) | Часто лучше при множестве конкурирующих потоков |\n| Совместимость с Virtual Threads | **Pinning** — виртуальный поток «прикрепляется» к носителю | Корректная работа — нет pinning |\n\n**Базовый паттерн использования ReentrantLock:**\n\n```java\nLock lock = new ReentrantLock();\n\nlock.lock();\ntry {\n    \u002F\u002F обновление общего состояния\n} finally {\n    lock.unlock(); \u002F\u002F ОБЯЗАТЕЛЬНО в finally\n}\n```\n\n**Попытка захвата с таймаутом:**\n\n```java\nif (lock.tryLock(500, TimeUnit.MILLISECONDS)) {\n    try {\n        \u002F\u002F критическая секция\n    } finally {\n        lock.unlock();\n    }\n} else {\n    \u002F\u002F не удалось захватить блокировку за 500 мс — альтернативная логика\n}\n```\n\n**Множественные Condition:**\n\n```java\nReentrantLock lock = new ReentrantLock();\nCondition notEmpty = lock.newCondition();\nCondition notFull = lock.newCondition();\n\n\u002F\u002F Производитель\nlock.lock();\ntry {\n    while (isFull()) notFull.await();\n    addItem(item);\n    notEmpty.signal();\n} finally {\n    lock.unlock();\n}\n```\n\nС `synchronized` вы ограничены единственным набором `wait()`\u002F`notify()` на объекте монитора, тогда как `ReentrantLock` позволяет создать несколько `Condition` (например, отдельно для «пусто» и «полно»), что делает код более выразительным и менее подверженным ошибкам.\n\n**Когда выбирать что:**\n- **`synchronized`** — для простых сценариев, коротких критических секций, когда не нужна расширенная функциональность.\n- **`ReentrantLock`** — когда нужны таймауты, прерываемое ожидание, множественные условия, fairness-политика, или при использовании Virtual Threads (чтобы избежать pinning).\n\n> **Аналогия:** `synchronized` — это автоматическая дверь с замком: вошёл — замок защёлкнулся, вышел — открылся автоматически. `ReentrantLock` — это сейф с ключом: больше возможностей (можно попробовать открыть, можно подождать определённое время, можно прервать ожидание), но ответственность за то, чтобы закрыть сейф обратно, лежит на вас.\n\n> **На собеседовании** часто спрашивают: «Когда вы предпочтёте `ReentrantLock` вместо `synchronized`?» Ключевые аргументы: tryLock с таймаутом для предотвращения deadlock, множественные Condition для producer-consumer, и отсутствие pinning при работе с Virtual Threads в Java 21+.","","middle",[15,16,17,18,19],"ReentrantLock","synchronized","блокировки","Lock","concurrency",[],null,{"title":23,"description":24,"ogTitle":25,"ogDescription":26,"keywords":27,"schemaAnswer":33,"featuredSnippetReady":34},"Различия между synchronized и ReentrantLock в Java — Gymterview","ReentrantLock предоставляет расширенные возможности блокировки: lock polling, прерываемое ожидание и высокую производительность при состязательности.","synchronized vs ReentrantLock — в чём разница?","ReentrantLock более масштабируем при состязании за ресурс, но требует явного unlock в finally. synchronized проще и автоматически снимает блокировку.",[28,29,30,31,32],"synchronized vs ReentrantLock","ReentrantLock Java","блокировка Java","Lock интерфейс","синхронизация потоков","ReentrantLock — реализация Lock, предоставляющая более тонкий контроль блокировки: lock polling, ожидание заданной длительности и прерываемое ожидание. ReentrantLock более масштабируем при высокой состязательности. Однако блокировку необходимо снимать вручную в finally-блоке. При отсутствии состязания synchronized может быть быстрее.",true]