Из-за неправильной записи.
Если ваш конструктор пишет в неконечные члены, они не должны быть зафиксированы в памяти сразу, и на самом деле они могут даже быть зафиксированы после переменной singleton. Java гарантирует, что поток, который влияет, видит последовательности по порядку, но не так, как другие потоки, если вы не установите барьер памяти.
См. этот вопрос и эту страницу спецификации Java для получения дополнительной информации.
Возможно, это не относится к делу, но в вашем примере вполне возможно, что два потока видят разные синглтоны. Предположим, что один поток проверяет недействительность переменной, вводит if
и получает прерывание, прежде чем он получает возможность построить объект. Новый поток, который получает ЦП, теперь тестирует объект с еще нулевым значением, создает синглтон. Когда старый поток снова запустится, он успешно завершит создание объекта и перезапишет переменную singleton.
Другая, более пугающая проблема возникает, если конструктор Resource вызывает метод, который в конечном итоге приведет к другому вызову этого getInstance. Даже если состояние программы не приводит к бесконечному циклу, вы создадите несколько одноэлементных экземпляров.