Размер ConcurrentLinkedQueue

Чтение Java ConcurrentLinkedQueue Docs, интересно, почему реализация не может сохранить размер:

Остерегайтесь того, что, в отличие от большинства коллекций, метод размера НЕ является операцией постоянного времени. Из-за асинхронности этих очередей определение текущего количества элементов требует обхода элементов.

Где в источник - это "асинхронный характер"? Я вижу только цикл while, чтобы повторять enqueing, пока AtomicReferences не будет соответствовать ожидаемым значениям/ссылкам. Почему невозможно увеличить значение size:AtomicInteger после успешного создания значения в очереди?

Спасибо большое.

Ответ 1

Представьте, что у вас есть два потока: один добавляет новый элемент, а другой - элемент. В начале нет элементов в очереди.

Предположим, что первый поток добавляет элемент, сразу же за ним следует другой поток, удаляющий элемент и уменьшающий размер, с которого ваш размер равен -1, тогда первый поток увеличивает размер до 0.

Немного надуманный пример, но вам нужно сделать всю операцию атомарной, чтобы гарантировать, что ни один другой поток не сможет получить доступ к размеру -1.

Ответ 2

Одним из важных преимуществ производительности ConcurrentLinkedQueue является тот факт, что вы не беспокоитесь о хвосте, когда вы обновляете голову, и наоборот, правильно?

Это означает, что в основном 2 потока могут опросить/предложить одновременно без вмешательства (если размер очереди не был 0, то есть).

Это было не так, если у вас был счетчик. Даже если это был AtomicInteger, который имеет хороший concurrency, у вас все еще будет повышенная вероятность неудачных операций CAS, потому что теперь у вас есть эта "горячая точка", которую вы обновляете каждый раз, когда вы проводите опрос/предложение.

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

Ответ 3

Почему невозможно увеличить размер: AtomicInteger после успешного завершения предлагая значение для очереди?

Возможно, потому что это предложение/декремент не может быть выполнено атомарно, не отрицательно влияя на метод concurrency метода.