Почему HashEntry в ConcurrentHashMap является финальным?

Я иду через исходный код ConcurrentHashMap в JDK 7 и у меня мало сомнений. Я уже прошел все вопросы по CHM на StackOverFlow, но не смог найти ответ.

  1. Гарантируется ли операция get в CHM для получения правильного значения, выставленного другим потоком? Я спрашиваю это, поскольку get не синхронизируется, если он не видит нулевое значение. Как нулевое значение гарантирует, что эта же запись обновляется другим потоком, а затем get используется с блокировкой?

  2. Это связано со статическим классом HashEntry, в котором хранятся ключ и значения.

a) Why is this class final? 
  is it just to make sure nobody subclasses it ?
  what happens if somebody subclasses it, is something wrong with that?
b)How does making next final helps in getting thread safety?   
c)Why is Key also final?     (I am not sure why Key is final in HashMap also)

1 ответ

Решение

Гарантируется ли операция get в CHM для получения правильного значения, выставленного другим потоком?

Это, безусловно, гарантировано, пока put завершил до вызова get, CHM использует volatile доступ и другие блокировки внутренне для обеспечения синхронизации данных, а не synchronized ключевое слово.

Я спрашиваю это, поскольку get не синхронизируется, если он не видит нулевое значение. Как нулевое значение гарантирует, что эта же запись обновляется другим потоком, а затем get используется с блокировкой?

Я предполагаю, что вы имеете в виду этот Javadoc:

Поскольку поле значения является изменчивым, а не окончательным, для несинхронизированного считывателя допустимо, чтобы модель памяти Java видела нулевое значение вместо исходного значения при чтении через гонку данных. Хотя переупорядочение, приводящее к этому, вряд ли когда-либо произойдет, метод Segment.readValueUnderLock используется в качестве резервной копии на случай, если нулевое (предварительно инициализированное) значение когда-либо будет замечено в методе несинхронизированного доступа.

Это пытается объяснить, что значение не является окончательным, поэтому инициализация в конструкторе может быть переупорядочена, и читатель может увидеть нулевое значение. Я предполагаю, что именно поэтому CHM не может хранить нулевые значения. Это позволяет им проверить на нулевое значение, а затем сделать еще один вход в синхронизированную блокировку. Не знал этого.

Для получения дополнительной информации о переупорядочении конструктора см.: Возможно ли переупорядочение инициализации экземпляра и присвоения общей переменной?

Почему HashEntry финал класса? Это просто чтобы убедиться, что никто не подкласс это?

Да. Это гарантирует, что класс не может быть разделен на подклассы. Это гарантирует неизменность. Если кто-то вложит его в подкласс, он может изменить видимость полей и разорвать контракт на параллелизм.

Как сделать следующий [[field]] final полезным для обеспечения безопасности потоков?

[[Извините, я неправильно понял этот вопрос]]. next поле (а также key а также hash поля) есть final потому что это гарантирует, что поле полностью инициализируется в конструкторе. Это, безусловно, повышает безопасность потока, поскольку оптимизатор не может переместить инициализацию за конец конструктора.

Смотрите выше информацию о value поле и как они защищают от него не будучи final который позволяет put(...) перезаписать.

Почему Ключ также окончательный? (Я не уверен, почему ключ является окончательным в HashMap)

Тот же ответ, что и HashEntry,

Другие вопросы по тегам