[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-mnogopotochnost-napishite-prosteyshiy-mnogopotochnyy-ogranichennyy-bufer-s-ispolzovaniem-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},292,"napishite-prosteyshiy-mnogopotochnyy-ogranichennyy-bufer-s-ispolzovaniem-reentrantlock",8,"mnogopotochnost","Многопоточность","🔀","Напишите простейший многопоточный ограниченный буфер с использованием ReentrantLock","\u003C!-- grade: 4\u002F5 — корректная реализация; добавлены комментарии и сравнение -->\n\nТа же задача «производитель-потребитель», но с использованием `ReentrantLock` и `Condition` вместо `synchronized` и `wait()`\u002F`notify()`.\n\n\u003Cdetails>\n\u003Csummary>Код: кольцевой буфер на ReentrantLock\u003C\u002Fsummary>\n\n```java\nclass QueueReentrantLock\u003CT> {\n    private volatile int size = 0;\n    private final Object[] content;\n    private final int capacity;\n\n    private int out;\n    private int in;\n\n    private final ReentrantLock lock = new ReentrantLock();\n    private final Condition isEmpty = lock.newCondition(); \u002F\u002F Условие «буфер пуст»\n    private final Condition isFull = lock.newCondition();  \u002F\u002F Условие «буфер полон»\n\n    QueueReentrantLock(int capacity) {\n        try {\n            lock.lock();\n            this.capacity = capacity;\n            content = new Object[capacity];\n            out = 0;\n            in = 0;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    private int cycleInc(int index) {\n        return (++index == capacity) ? 0 : index;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    T get() throws InterruptedException {\n        try {\n            lock.lockInterruptibly();\n            while (size == 0) {\n                isEmpty.await(); \u002F\u002F Ждём появления элемента\n            }\n            final Object value = content[out];\n            content[out] = null;\n            if (size > 1) {\n                out = cycleInc(out);\n            }\n            size--;\n            isFull.signal(); \u002F\u002F Уведомляем производителя\n            return (T) value;\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    QueueReentrantLock\u003CT> put(T value) throws InterruptedException {\n        try {\n            lock.lockInterruptibly();\n            while (size == capacity) {\n                isFull.await(); \u002F\u002F Ждём освобождения места\n            }\n            if (size == 0) {\n                content[in] = value;\n            } else {\n                in = cycleInc(in);\n                content[in] = value;\n            }\n            size++;\n            isEmpty.signal(); \u002F\u002F Уведомляем потребителя\n        } finally {\n            lock.unlock();\n        }\n        return this;\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n**Преимущества ReentrantLock-версии перед synchronized-версией:**\n\n| Аспект | `synchronized` версия | `ReentrantLock` версия |\n|---|---|---|\n| Управление условиями | Два отдельных объекта-монитора | Два `Condition` от одного `Lock` |\n| Прерываемое ожидание | Нет (wait не прерываем по `lockInterruptibly`) | Да (`lockInterruptibly`) |\n| Структура кода | Множество `synchronized` блоков | Один `lock`\u002F`unlock` на метод |\n| Количество блокировок | Три (this, isEmpty, isFull) | Одна (`lock`) |\n\n> **На собеседовании** часто просят сравнить две реализации. Ключевое преимущество `ReentrantLock` — единый замок с множественными условиями (`Condition`), что делает код чище и менее подверженным ошибкам, чем использование нескольких объектов-мониторов.","","senior",[15,16,17,18,19],"synchronized","wait-notify","буфер","producer-consumer","concurrency",[],null,{"title":23,"description":24,"ogTitle":25,"ogDescription":26,"keywords":27,"schemaAnswer":33,"featuredSnippetReady":34},"Ограниченный буфер на synchronized в Java — производитель-потребитель — Gymterview","Реализация многопоточного bounded buffer с synchronized, wait() и notify(). Циклический массив с методами put() и get() для паттерна producer-consumer.","Bounded Buffer на synchronized — producer-consumer в Java","Циклический буфер на synchronized: put() блокируется при заполнении, get() — при пустом буфере. Синхронизация через wait\u002Fnotify.",[28,29,30,31,32],"ограниченный буфер Java","synchronized буфер","producer consumer Java","bounded buffer","wait notify пример","Ограниченный буфер реализуется как циклический массив с двумя указателями (in, out) и volatile size. Метод put() блокируется через wait() при заполненном буфере и уведомляет через notify() о наличии данных. Метод get() блокируется при пустом буфере. Используются отдельные объекты-мониторы isEmpty и isFull.",true]