В моем приложении мне нужно установить переменную лениво, поскольку у меня нет доступа к необходимым методам во время инициализации класса, но мне также нужно, чтобы это значение было доступно для нескольких потоков.Я знаю, что мог бы использовать дважды проверенную блокировку , чтобы решить эту проблему, но это кажется излишним. Метод, который мне нужно вызвать для получения значения, идемпотентен, и возвращаемое значение никогда не изменится. Я бы хотел лениво инициализировать ссылку, как если бы я находился в однопоточном окружении.Кажется, что это должно работать, поскольку чтение и запись в ссылки являются атомарными. [ 1 ] [ 2 ]
Вот пример кода для того, что я делаю.
// views should only be accessed in getViews() since it is
// lazily initialized. Call getViews() to get the value of views.
private List<String> views;
/* ... */
private List<String> getViews(ServletContext servletContext) {
List<String> views = this.views;
if (views == null) {
// Servlet Context context and init parameters cannot change after
// ServletContext initialization:
// https://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#setInitParameter(java.lang.String,%20java.lang.String)
String viewsListString = servletContext.getInitParameter(
"my.views.list.VIEWS_LIST");
views = ListUtil.toUnmodifiableList(viewsListString);
this.views = views;
}
return views;
}
Этот вопрос о 32-битных примитивах похож на , но я хочу подтвердить, что поведение аналогично для ссылок на объекты типа String
s и List
s..
По-видимому, это должно работать нормально, поскольку каждый поток либо увидит null
и пересчитает значение (не проблема, так как значение никогда не изменится), либо увидит уже вычисленное значение.Я пропускаю какие-либо подводные камни здесь?Этот код является потокобезопасным?