Если я вас правильно понял, вы ожидаете, что один поток (давайте назовем его A ) будет ожидать другого (что увеличивает значение до 19, B ), а затем пропустите приращение, потому что nextValue
равно 19 и не равно нулю. Но изменение невидимо ожидающим потоком.
Возможный сценарий намного сложнее, как я вижу:
Проблема в том, что 19 возвращается A * Поток 1013 *, который ожидает, поскольку он сразу пропускает весь блок после того, как переменное значение будет опубликовано потоком B в строке:
nextValue = rangeFetch.getAndIncrementAsString(name);
В другом случае поток A входит в метод, а nextValue
уже опубликован.
Таким образом, он немедленно переходит к оператору return и return 19, который был установлен B тема (Да, это неожиданно, но иногда это случается). Не следует ожидать, что поток A будет ожидать завершения выполнения B до sh. B (который первым достиг синхронизированного блока) завершает sh обработку (приращение) значения и возвращает 20.
Однако для этого есть возможные обходные пути:
if (nextValue == null) {
synchronized(this) {
if(nextValue == null) {
String localTemp = rangeFetch.getAndIncrementAsString(name);
idMapper.mapToB(SOME_CONST, correlationId, localTemp, DURATION);
nextValue = localTemp;
}
}
}
Суть в том, что изменения, внесенные в nextValue
немедленно , влияют на другие вызовы getNextIncrement
.
В этом шаблоне действительно сложно отладить проблемы, поэтому я могу неправильно, но я все равно выкладываю ответ, так как мое объяснение слишком длинное для комментария.