Гарантируется ли выполнение HttpSessionListener.sessionCreated () до того, как какой-либо другой поток получит доступ к новому сеансу? - PullRequest
0 голосов
/ 05 ноября 2018

Я пытаюсь кэшировать значения в ConcurrentHashMap в Session. Чтобы избежать условий гонки и убедиться, что моя карта создана до того, как какие-либо потоки попытаются ее использовать, я использую HttpSessionListener.sessionCreated(), чтобы добавить карту в Session:

@Override
public void sessionCreated(HttpSessionEvent event) {

    event.getSession()
        .setAttribute(MY_CACHE_KEY, new ConcurrentHashMap());

}

Гарантируется ли выполнение этого кода до того, как другие потоки получат доступ к сеансу (например, через request.getSession())?

Я посмотрел на HttpSessionListener JavaDoc и Servlet 4.0 Spec. и, похоже, нет никаких гарантий безопасности потоков.

Серлвет Спец. ссылается на безопасность потока сеанса несколько раз, но ни одна из этих ссылок не относится к слушателям сеанса и созданию сеанса, как я их понимаю:

7.7.1 Проблемы с потоками

Несколько сервлетов, выполняющих потоки запросов, могут иметь активный доступ к одному и тому же объекту сеанса в одно и то же время. Контейнер должен обеспечивать манипулирование внутренними структурами данных, представляющими атрибуты сеанса. выполняется потокобезопасным способом. Разработчик несет ответственность за потокобезопасный доступ к самим объектам атрибута. Это защитит коллекцию атрибутов внутри объекта HttpSession от одновременного доступа, исключение возможности для приложения вызывать повреждение этой коллекции. Если явно не указано иное в спецификации (например, в разделе 7.7.1, «Проблемы с многопоточностью» на стр. 7-67 для объектов сеанса), объекты, полученные из запроса или ответа, должны считаться не поточно-безопасными. Это включает, но не ограничивается, PrintWriter, возвращенный из ServletResponse.getWriter () и OutputStream возвращаются из ServletResponse.getOutputStream ().


11.5 Экземпляры и потоки слушателя

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

Изменения атрибутов в объектах ServletContext и HttpSession могут происходить одновременно. Контейнеру не требуется синхронизировать полученные уведомления с атрибутивными классами слушателей. Классы слушателей, которые поддерживают состояние, несут ответственность за целостность данных и должны явно обрабатывать этот случай.

Кажется очевидным, что sessionCreated() должно завершиться до того, как потоки получат доступ к сеансу, но "очевидно правильный код" был небезопасен для многопоточности до .

Эта неоднозначность не существует для ServletContextLister.contextInitialized(), поскольку она гарантированно завершится до инициализации Servlet, а Servlet.init() гарантированно будет однопоточной и будет выполняться перед любыми запросами .


По крайней мере, я протестировал Tomcat, и он гарантирует, что sessionCreated() завершится до того, как request.getSession() вернется. Я проверил, установив точку останова в sessionCreated() и отправив запрос с именем request.getSession(). Этот запрос не был выполнен, пока я не продолжил с точки останова. Однако поведение одной реализации контейнера Servlet не является убедительным доказательством того, что все контейнеры / серверы ведут себя таким образом.

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