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 не сравнивает поля вообще. Он просто сравнивает, является ли это той же ссылкой, тем же указателем в памяти, или как вы хотите это назвать.