Java String механизм кэширования hashcode

Глядя на класс Java String, мы можем видеть, что хэш-код кэшируется после первой оценки.

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

Где hash - переменная экземпляра. У меня есть вопрос, зачем нам нужна дополнительная переменная h?

Ответ 1

Просто потому, что значение hash изменяется в цикле, и ваше решение без промежуточной временной переменной не является потокобезопасным. Учтите, что этот метод вызывается в нескольких потоках.

Скажите thread-1 начатое hash вычисление, и оно больше не 0. Через несколько минут thread-2 вызывает тот же метод hashCode() на том же объекте и видит, что hash не 0, но thread-1 еще не закончил вычисление. В результате в thread-2 будет использоваться неправильное значение hash (не полностью вычисленное).

Ответ 2

Это простой и дешевый механизм синхронизации.

Если поток вызывает hashCode() в первый раз, а второй поток вызывает его снова, когда первый поток вычисляет хэш, второй поток возвращает неправильный хеш (промежуточное значение вычисления в первом потоке) если вы используете непосредственно атрибут.

Ответ 3

Это очень просто: локальный примитив h хорошо локален; таким образом, поточно-безопасный; в отличие от hash, который является общим.