В соответствии с the Java Language Specification конструкторы не могут быть помечены как синхронизированные, потому что другие потоки не могут видеть создаваемый объект, пока поток, создающий его, не завершит его. Это кажется немного странным, потому что я действительно может иметь другой поток просмотра объекта, пока он строится:Почему нельзя синхронизировать конструкторы Java?
public class Test {
public Test() {
final Test me = this;
new Thread() {
@Override
public void run() {
// ... Reference 'me,' the object being constructed
}
}.start();
}
}
Я знаю, что это довольно надуманный пример, но, кажется, в теории, что кто-то мог придумать более реалистичный случай, когда обозначение синхронизированного конструктора было бы законным, чтобы предотвратить гонки с такими потоками.
Мой вопрос заключается в следующем: есть ли причина, по которой Java специально запретит синхронизированный модификатор на конструкторе? Возможно, мой приведенный выше пример ошибочен, или, возможно, нет причин, и это произвольное дизайнерское решение. В любом случае мне действительно любопытно и хотелось бы узнать ответ.
В стороне, настоятельно рекомендуется не допускать «эта» ссылка для выхода до завершения конструктора. –
@Mike Q- Я слышал это раньше, но не совсем понимаю почему. Есть ли какая-то особая причина? Я мог видеть, что Bad Things происходит, если вы дали ссылку на это до того, как закончите инициализацию объекта, но что, если это последнее, что вы делаете в конструкторе? – templatetypedef
это действительно вопрос другого вопроса, но даже если это последнее, что вы делаете в конструкторе, если объект подклассифицирован, то подкласс не завершил построение. Если этот класс является окончательным, и вы не создаете цепочку конструкторов (называете это (...)) и делаете что-то еще после вызова цепи, и это последнее, что вы делаете, это прекрасно. Кроме того, что любое из этих решений может измениться (позже вы можете добавить второй конструктор). – Yishai