Ответ 1
Фокус в том, что replace(K key, V oldValue, V newValue)
обеспечивает атомарность для вас. Из документов (внимание мое):
Заменяет запись для ключа только, если в настоящее время отображается на заданное значение.... действие выполняется атомарно.
Ключевое слово "атомарно". Внутри replace
"проверьте, является ли старое значение ожидаемым, и только если оно есть, замените его" происходит как один кусок работы, без каких-либо других потоков, способных чередоваться с ним. Это для реализации, чтобы выполнить любую синхронизацию, необходимую для обеспечения этой атомарности.
Таким образом, не может быть, что оба потока видят currentAction == 1
из функции replace
. Один из них увидит его как 1, и поэтому его обращение к replace
вернет true. Другой будет видеть его как 2 (из-за первого вызова) и, таким образом, вернуть false — и повторите попытку, чтобы повторить попытку, на этот раз с новым значением currentAction == 2
.
Конечно, может быть, что третий поток обновил currentAction до 3 в то время, и в этом случае этот второй поток будет просто продолжать попытки, пока ему не повезет, чтобы никто не прыгнул впереди него.