Дважды проверенная блокировка имеет серьезные недостатки. Проблема в том, что этот оператор почти наверняка присваивает несколько переменных:
searchBox = new SearchBox();
Помимо присвоения searchBox
, будет также несколько других назначений для инициализации нового экземпляра SearchBox
.
Любой другой поток, который пытается посмотреть на searchBox
без синхронизации , может видеть, что эти назначения происходят в другом порядке , чем они произошли впоток, который создал синглтон.
Это означает, что если поток A создает синглтон, а затем поток B приходит и впоследствии находит searchBox != null
, то поток B не войдет в synchronized
блок и поток B могут видеть одноэлементный объект в неинициализированном или частично инициализированном состоянии.
Одноэлементный объект должен быть безопасно опубликован . Комментарий Энди Тернера к исходному вопросу (см. Выше) называет несколько различных способов сделать это.
PS: Вы можете «исправить» двойную проверку блокировки, объявив переменную searchBox
равной volatile
, но тогда стоимость доступа к searchBox
становится почти такой же высокой, как стоимость блокировки замка. Лучше просто использовать один из шаблонов безопасной публикации, упомянутых выше.