Это вопрос не о том, как работает LongAdder, а о интригующей детали реализации, которую я не могу понять.LongAdder Striped64 wasUncontent detail detail
Вот код из Striped64 (я вырезал некоторые части и оставил соответствующие части для вопроса):
final void longAccumulate(long x, LongBinaryOperator fn,
boolean wasUncontended) {
int h;
if ((h = getProbe()) == 0) {
ThreadLocalRandom.current(); // force initialization
h = getProbe();
wasUncontended = true;
}
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
//logic to insert the Cell in the array
}
// CAS already known to fail
else if (!wasUncontended) {
wasUncontended = true; // Continue after rehash
}
else if (a.cas(v = a.value, ((fn == null) ? v + x : fn.applyAsLong(v, x)))){
break;
}
Многое из кода понятно мне, за исключением:
// CAS already known to fail
else if (!wasUncontended) {
wasUncontended = true; // Continue after rehash
}
Где эта уверенность в том, что следующий CAS не сработает? Это действительно сбивает с толку для меня, потому что эта проверка имеет смысл только для одного случая: когда какая-то нить входит в метод longAccumulate для n-го раза (n> 1) ,
Это как этот код говорит: если вы (какая-то тема) были здесь раньше, и у вас есть некоторая разногласия в определенном слоте ячейки, не пытайтесь использовать значение CAS для уже существующего, но вместо этого перефразируйте зонд.
Я искренне надеюсь, что я кое-что получу для кого-то.
1) Я знаю, откуда это происходит, но THX для добавления его в любом случае. 2) Черт возьми! Я думал, что * CAS, уже известный с ошибкой *, означает, что следующая операция CAS завершится неудачно, а не предыдущая. Мне нравится ваша догадка, у них, вероятно, были тесты, которые доказывают это как оптимальное дополнение к коду. Ваш вклад очень ценится. – Eugene
Да, я на 99% уверен в вашей теории (посмотрев код снова). Это противоречит интуиции для меня, но может быть, это имеет смысл для кого-то, кто поддерживает этот код. Еще раз спасибо, и я соглашусь с этим. – Eugene
Да, это самое разумное объяснение. Попробуйте сжатый контур с инкрементами целого числа с CAS. Под тяжелым соперничеством вы можете легко получить 90 +% неудачный CAS. – Voo