Очередь без блокировки и с ограниченным размером в Java

Я пытаюсь расширить реализацию очереди без блокировки в Java согласно этой публикации.

Для моей реализации я ограничен в использовании только атомарных переменных / ссылок. Кроме того, моя очередь должна иметь максимальный размер. И поэтому putObject() должен блокироваться, когда очередь заполнена, и getObject(), если очередь пуста.

На данный момент я не знаю, как решить эту проблему без использования замков.

Например, при использовании AtomicInteger операции модификации будут атомарными. Но есть еще проблема, что я должен обработать ситуацию проверки и изменения в putObject() и getObject(), верно? Таким образом, все еще существует ситуация, когда поток очереди будет прерван после проверки текущего размера очереди.

На данный момент у меня вопрос, можно ли решить эту проблему с моими нынешними ограничениями?

поздравил

2 ответа

Если у вас есть жизнеспособная, правильно работающая очередь без блокировки, добавить максимальный размер можно так же просто, как просто добавить AtomicInteger и выполнить проверки inc, dec в нужное время.

При добавлении элемента вы в основном заранее резервируете место в очереди. Что-то вроде:

while (true) {
    int curr = count.get();
    if (curr < MAX) {
        if (count.compareAndSet(curr, curr + 1)) {
            break;
        }
    }
    else {
        return FULL;
    }
}

Затем вы добавляете новый элемент и связываете его. Получая, вы можете просто получить доступ к голове как обычно и проверить, есть ли что-нибудь, что можно вернуть из очереди. Если да, вы возвращаете его, а затем уменьшаете счетчик. Если нет, просто верните ПУСТО. Обратите внимание, что я не использую счетчик, чтобы проверить, действительно ли очередь пуста, поскольку счетчик может быть равен 1, в то время как в очередь еще ничего не связано из-за подхода с предварительным резервированием. Поэтому я просто верю, что у вашей очереди есть способ сказать вам "у меня есть что-то во мне" или нет (это должно быть, или get() никогда не сработает).

Это очень распространенная проблема, которая обычно решается с помощью кольцевого буфера. Это то, что используют сетевые адаптеры, так же как и библиотека Disruptor. Я предлагаю вам взглянуть на Disruptor и хороший пример того, что вы можете сделать с кольцевыми буферами.

Другие вопросы по тегам