РЕДАКТИРОВАТЬ После комментария, в котором предлагался компилятор, включающий приватный конструктор (я не думал об этой оптимизации), есть вероятность, что код будет небезопасным. И наихудшая часть небезопасного многопоточного кода - это то, что он работает, поэтому лучше избегать его полностью. Если вы хотите разыграть разные трюки (вы действительно хотите по какой-то причине избежать фабрики), подумайте о добавлении оболочки, чтобы гарантировать согласованность данных во внутреннем объекте реализации и зарегистрироваться во внешнем объекте.
Я предполагаю, что это будет хрупким, но хорошо. Компилятор не может знать, будет ли внутренний конструктор вызываться только из других конструкторов или нет, поэтому он должен убедиться, что результат будет правильным для кода, вызывающего только внутренний конструктор, поэтому какой бы механизм он не использовал (барьер памяти?) Имеет быть там на месте.
Я бы предположил, что компилятор добавит барьер памяти в конце каждого конструктора. Проблема все еще существует: вы передаете ссылку this
на другой код (возможно, на другие потоки) до того, как он будет полностью создан - это плохо - но если единственная оставшаяся «конструкция» - это регистрация слушателя, тогда состояние объекта будет таким же стабильным, как и когда-либо.
Решение является хрупким , так как в какой-то день вам или другому программисту может понадобиться добавить еще один член к объекту, и вы можете забыть, что цепочечные конструкторы являются уловкой параллелизма и могут решить инициализировать поле в общедоступном конструкторе, и при этом добавится трудно обнаружить потенциальную гонку данных в вашем приложении, поэтому я постараюсь избежать этой конструкции.
Кстати: предполагаемая безопасность может быть неправильной. Я не знаю, насколько сложным / умным является компилятор, и является ли барьер памяти (или тому подобное) чем-то, что он может попытаться оптимизировать ... так как конструктор является закрытым, у компилятора достаточно информации, чтобы знать, что это вызывается только из других конструкторов, и этого достаточно для определения того, что механизм синхронизации не нужен во внутреннем конструкторе ...