AtomicReference

У меня есть несколько вопросов о методе AtomicReference.compareAndSet(), согласно документу, он сказал:

Атомно устанавливает значение для данного обновленного значения, если текущее значение == ожидаемое значение.

Насколько я понимаю, == оператор сравнивает адрес двух объектов, если так, как это будет работать в примерах, подобных этому

private AtomicReference<AccessStatistics> stats =
    new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
    AccessStatistics prev, newValue;
    do {
        prev = stats.get();
        int noPages = prev.getNoPages() + 1;
        int noErrors = prev.getNoErrors;
        if (wasError) {
           noErrors++;
        }
        newValue = new AccessStatistics(noPages, noErrors);
    } while (!stats.compareAndSet(prev, newValue));
}

В этом фрагменте кода, как jvm знает, какие поля AccessStatistics должны быть сопоставлены в compareAndSet()? На самом деле мне просто интересно, как работает вся эта стратегия, учитывая, что Java не позволяет переопределить == совсем? Спасибо за любые комментарии!

2 ответа

Решение

Как jvm узнает, какие поля AccessStatistics должны сравниваться в compareAndSet()?

Это не так. Это не сравнение полей в объекте. Это просто сравнение ссылки на объект, о чем говорится в документации. Вот только как AtomicReference классные работы. Как вы упоминаете из Javadocs, он использует == а не equals() метод.

Атомно устанавливает значение для данного обновленного значения, если текущее значение == ожидаемое значение.

Все Atomic* классы имеют схожие функции. Это позволяет вам атомарно устанавливать значения, будучи уверенным, что другой поток не перезаписывает ваше значение. С compareAndSet(...) Вы должны указать текущую ссылку на объект, чтобы убедиться, что вы обновляете его должным образом.

В вашем фрагменте кода он пытается добавить объект неизменяемой статистики доступа. Таким образом, он получает текущее значение, добавляет к нему, а затем сохраняет новую статистику для ссылки. Если другой поток сохранил свою статистику в это время, то compareAndSet вернет false, и он зацикливается и пытается снова. Это решает условия гонки без необходимости иметь synchronized блок.

JVM не сравнивает поля вообще. Он просто сравнивает, является ли это той же ссылкой, тем же указателем в памяти, или как вы хотите это назвать.

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