Я реализовал очередь экземпляров запросов FIFO (предварительно назначенные объекты запроса для скорости) и начал с использования "синхронизированного" ключевого слова в методе добавления. Метод был довольно коротким (проверьте, есть ли место в буфере фиксированного размера, а затем добавьте значение в массив). Используя visualVM, казалось, что поток блокировался чаще, чем мне нравилось ( "монитор", если быть точным). Поэтому я преобразовал код для использования значений AtomicInteger для таких вещей, как отслеживание текущего размера, а затем использование compareAndSet() в циклах (как AtomicInteger делает внутренне для таких методов, как incrementAndGet()). Теперь код выглядит довольно долго.
То, что мне было интересно, - это накладные расходы на производительность использования синхронизированного и более короткого кода по сравнению с более длинным кодом без синхронизированного ключевого слова (поэтому никогда не блокировать блокировку).
Вот старый метод get с синхронизированным ключевым словом:
public synchronized Request get()
{
if (head == tail)
{
return null;
}
Request r = requests[head];
head = (head + 1) % requests.length;
return r;
}
Вот новый метод get без синхронизированного ключевого слова:
public Request get()
{
while (true)
{
int current = size.get();
if (current <= 0)
{
return null;
}
if (size.compareAndSet(current, current - 1))
{
break;
}
}
while (true)
{
int current = head.get();
int nextHead = (current + 1) % requests.length;
if (head.compareAndSet(current, nextHead))
{
return requests[current];
}
}
}
Мое предположение заключалось в том, что синхронизированное ключевое слово хуже из-за риска блокировки блокировки (потенциально вызывающих переключатели контекста потока и т.д.), хотя код короче.
Спасибо!