Комментарии 30
Понятно, при сравнении двух обёрток оператором == (!=) никакого autoboxing не происходит. Вообще говоря, именно первое равенство смущает. Дело в том, что для целых значений i: -129 < i < 128 объекты-обёртки Integer кэшируются. Поэтому для i из этого диапазона Integer.valueOf(i) не создаёт каждый раз новый объект, а возвращает уже созданный.
А вот если бы не принудительный, где надо и не надо, ООП то этого бессмысленного дроча бы не было. По моему мнению если даже для сравнения чисел мне надо иметь ввиду какие то грабли, то тут явно что то не так…
Вообще говоря, синглтоны считаются не самой лучшей практикой.
Как вежливо и дипломатично получилось.
Жёстче надо с ними, синглтоны — вирусное зло в ООП и неисчерпаемый источник граблей!))
Для некоторых платформ улучшение возможно — по ссылке в статье Шипилев показал небольшую разницу для ARM.
На x86 разницы быть действительно не может — там чтение из volatile «бесплатное» (нет оверхеда, если не считать запрет на reordering)
Дело в том, что для целых значений i: -129 < i < 128 объекты-обёртки Integer кэшируются.
Для начинающих и не только:
Я бы добавил еще что нет верхнего предела. Точнее он есть, но его можно изменить.
github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Integer.java#L1010
hashCode не является адресом объекта, кажется, ещё с версии 1.2. Что изменилось в Java 9 — так это исправили javadoc. Однако даже до этого было сказано, что оно может быть реализовано так, но это не требуется спецификацией. Не стоит выдавать желаемое за действительное.
Однако, при помощи -XX:hashCode=4
можно вернуть желаемое поведение.
Версии java, начиная с которой поведение изменилось, в статье не указывалось.
Согласен, в данном месте следовало вставить оговорку, что это являлось особенностью конкретной jvm и спецификацией не требовалось. Сейчас вставлю.
Когда-то это было так.Теперь, как минимум с 11-ой версии java, это не так.
Как минимум с 9ой исправлен javadoc — и даже в минимум Sun JRE 1.2 hashCode не возвращал адрес объекта. Т.е референс, что когда-то это было так — сомнительный.
hashCode не может возвращать адрес объекта с тех пор, как GC научился эти самые объекты перемещать (естественно, не меняя их хеш-кода)
может или не может — это вопрос второй, в теории никто не запрещает это делать, ведь hash-функция нужна для того, чтобы превращать поиск в hash-структурах из O(N) в O(1).
Но коллизии неизбежны
Как раз таки запрещает: значение хеш-функции обязано быть детерминированным, и не имеет права меняться в ходе сборки мусора. Иначе положенные в хеш-таблицу записи потом будет не найти.
Подход не работает по следующим причинам. (read 1, check 1) и (read 3) не синхронизированы. По концепции модели памяти java, изменения, сделанные в другом потоке, могут быть невидимы нашему потоку, пока мы не синхронизируемся.
Здесь вы неправильно описываете проблему. Да, read1 и read3 не синхронизированы, но проблема не в другом потоке. А в том, что несинхронизированные чтения могут быть переупорядочены, т.е. read1 != null, но read3 == null. И заодно, из-за "instance = new Singleton();" мы можем получить ссылку на объект до того, как он был до конца сконструирован, и это действительно проблема синхронизации с другим потоком, но не read1 и read3, а read3 и доступа к членам instance.
И заодно, из-за «instance = new Singleton();» мы можем получить ссылку на объект до того, как он был до конца сконструирован
А разве ссылка на объект не будет сохранена в поле instance только после завершения работы конструктора (вызова )? Можете показать пример, доказывающий Ваше утверждение? (случай утечек ссылок this из самого конструктора исключаем)
Java Memory Model.
Другой поток может увидеть, что в instance сохранена ссылка на объект, но не увидеть записи в члены объекта, если нет happens-before между его чтениями и записями создавшего объект потока. А если читающий поток не заходил в syncronized, а он мог не заходить, то happens-before нет.
И примеры в статье-источнике, которые показывают, что оно таки ломается.
Есть хороший доклад Ивана Углянского, посвящённый всем тонкостям финализации: https://www.youtube.com/watch?v=XtijbFcQxyw
Java: вещи, которые могут показаться любопытными и разработчику со стажем