Использование локальной переменной при инициализации статической переменной - PullRequest
0 голосов
/ 21 ноября 2018

В исходном коде java.util.Scanner я нашел следующие статические служебные методы:

private static Pattern separatorPattern() {
    Pattern sp = separatorPattern;
    if (sp == null)
        separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
    return sp;
}

private static Pattern linePattern() {
    Pattern lp = linePattern;
    if (lp == null)
        linePattern = lp = Pattern.compile(LINE_PATTERN);
    return lp;
}

Почему это было сделано таким сложным способом, а не просто, скажем,

private static Pattern linePattern() {
    if (linePattern == null)
        linePattern = Pattern.compile(LINE_PATTERN);
    return linePattern;
}

Какой смысл использовать здесь локальную переменную (lp)?Это какая-то техника оптимизации?Или, возможно, предосторожность против одновременной модификации?Но linePattern не может быть снова установлен на null, так как этот метод является единственным местом, где он модифицирован.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Я думаю, что они хотят избежать чтения из поля volatile дважды.

  • один раз, чтобы проверить, является ли оно null
  • один раз для return

В своей версии они только

  • один раз считали ее в локальную переменную
  • подтверждают, что локальная переменная не равна нулю
  • returnэта локальная переменная

Оптимизация для «счастливого пути», который происходит невероятно чаще, чем «начальный путь установки», который происходит только один раз - или, самое большее, несколько раз, если метод вызываетсяодновременно до завершения инициализации.

Или, возможно, меры предосторожности против одновременной модификации?

Таких мер предосторожности нет.Если вы вызываете linePattern одновременно до того, как он закончит установку статического изменчивого поля, шаблон будет создаваться несколько раз (но это нормально), будут возвращаться разные экземпляры, и будет выбираться случайный из них для сохранения (это такжехорошо, так как они эквивалентны).

Любые меры предосторожности против этого только увеличат стоимость нашего «счастливого пути», поэтому его следует выполнять только в ситуациях, когда по какой-то причине экземпляр действительно должен быть единичным.

0 голосов
/ 21 ноября 2018

Я полагаю, что это ключевое слово volatile, используемое с полями linePattern и separatorPattern

private static volatile Pattern separatorPattern;
private static volatile Pattern linePattern;

Из-за спецификации

Язык программирования Java позволяет потокам обращаться к общим переменным (§17.1).Как правило, чтобы обеспечить постоянное и надежное обновление общих переменных, поток должен обеспечить исключительное использование таких переменных путем получения блокировки, которая обычно обеспечивает взаимное исключение для этих общих переменных.

Язык программирования Java предоставляет второй механизм, изменяемые поля, который более удобен, чем блокировка для некоторых целей.

Поле может быть объявлено как изменяемое, и в этом случае модель памяти Java гарантирует, что все потоки видят согласованное значение дляпеременная

Также здесь мы можем прочитать, что

Объявление изменчивой переменной Java означает:

  • Значение этой переменной никогда не будет кэшировано локально: все операции чтения и записи будут идти прямо в «основную память»;

  • Доступ к переменной действует так, как будто она заключена всинхронизированный блок, синхронизированный сам по себе.

Вот почему они сначала пытаются напрямую перезапуститьзначение рекламного поля, а затем перезаписать его новым значением

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...