2013-05-29 3 views
3

См. Это blog и этот topic.Изменение порядка изменения модифицированного String.hashCode()

Кажется, что код будет изменен даже в одном потоке?

public int hashCode() { 
if (hash == 0) { // (1) 
    int off = offset; 
    char val[] = value; 
    int len = count; 

    int h = 0; 
    for (int i = 0; i < len; i++) { 
     h = 31*h + val[off++]; 
    } 
    hash = h; 
    } 
    return hash; // (2) 
} 

Но его действительно сбивает с толку меня, почему (2) может вернуть 0 и (1) может быть отличен от нуля?

Если я использую код в одном потоке, это даже не будет работать, как это может произойти?

+0

Это проблема многопоточности. –

+0

Him @MarkoTopolnik, Как можно выполнить переупорядочение в многопоточном режиме? Я не уверен, но я думаю, что ** переупорядочение ** выполняется в байт-коде, который ничего не делает с потоками? – MrROY

+0

Переупорядочение определенно не происходит на уровне байт-кода; это проблема, связанная с компилятором JIT. Вы гарантированно должны иметь нормальное поведение внутри одного потока. –

ответ

0

Первый вопрос:

Will переназначение инструкций произойдет в однотридовом исполнении?

Ответ:

Изменение порядка команд является оптимизация компилятора. Порядок инструкций в одном потоке будет таким же, независимо от того, сколько потоков задействовано. Или: Да и в одном потоке.

Второй вопрос:

Почему это могло привести к проблеме в многопоточности, но не с одной нитью?

Ответ:

Правила этого переназначения предназначены для гарантирую, что нет никаких странных эффектов в однотридовой или правильно синхронизированного кода. Это означает: если мы пишем код, который не является ни одним, ни правильно синхронизированным, могут быть странные эффекты, и мы должны понимать правила и стараться избегать этих эффектов.

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

Edit: Третий вопрос:

И снова, что на самом деле происходит?

Ответ:

Когда мы смотрим на код, он будет иметь дело хорошо с не видя изменения другого thread.So первое, что мы должны понять: метод не возвращает переменную, ни constanst ни буква. Нет способа вернуть то, что находится поверх стека, когда счетчик программ сброшен. Это должно быть инициализировано в некоторый момент времени, и оно может быть перезаписано позже. Это означает, что он может быть сначала инициализирован содержимым hash (0 сейчас), затем другой поток заканчивает вычисление и устанавливает hash на что-то, а затем происходит проверка hash == 0. В свою очередь, возвращаемое значение больше не перезаписывается и возвращается 0.

Итак, точка: возвращаемое значение может изменяться независимо от возвращаемой переменной, так как это не то же самое. Современный язык программирования делает его похожим на то, чтобы сделать нашу жизнь проще. Но эта абстракция как целостность, когда вы не придерживаетесь правил.

+0

Повторное упорядочение может происходить в однопоточной среде, но оно не создаст неожиданного поведения, поскольку неожиданное поведение связано с изменением поля в другом потоке, тогда как текущий поток оптимизирован и не видит обновленного значения. – nhahtdh

+0

@nhahtdh Надеюсь, мое редактирование упростит ситуацию. –

+0

Где именно выполняется проверка хэша == 0? – MrROY

1

Первая точка java memory model является:

Каждое действие в потоке происходит перед каждым действием в этом потоке , который приходит позже, чтобы программы.

Именно поэтому переупорядочение в одном потоке невозможно. Пока код не синхронизирован, такие гарантии не предусмотрены для нескольких потоков.

Посмотрите на реализацию строки hashCode. Сначала он загружает хэш в локальную переменную и только затем выполняет проверку и возврат. Так предотвращаются такие переупорядочивания. Но это не спасает нас от нескольких вычислений hashCode.

+0

Я считаю, что переупорядочение не предотвращается в однопоточной программе. Он просто не будет замечен в одном потоке. – MrROY

Смежные вопросы