Является ли HttpSession потокобезопасным, являются ли потокобезопасными операции set / get Attribute?

StackOverflow https://stackoverflow.com/questions/616601

Вопрос

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

Кроме того, я читал в Интернете, что некоторые предлагают использовать:

synchronized(session) {
  session.setAttribute("abc", "abc");
}

Является ли это обоснованным предложением?

Это было полезно?

Решение

Нет, согласно IBM - теория и практика Java - нет. : Все ли веб-приложения с состоянием повреждены? . Вам нужно синхронизировать.

Как HttpSession не безопасен для потоков из ранчо Java тоже может быть полезным.

Другие советы

Servlet 2.5 spec:

  

Несколько сервлетов, выполняющих запрос   потоки могут иметь активный доступ к   тот же объект сеанса в то же время.   Контейнер должен гарантировать, что   манипулирование внутренними данными   структуры, представляющие сессию   Атрибуты выполняются в   Безопасный способ. Разработчик имеет   ответственность за безопасность потоков   доступ к объектам атрибута   самих себя. Это защитит   коллекция атрибутов внутри   HttpSession объект из параллельного   доступ, исключая возможность   для приложения, чтобы вызвать это   коллекция стала поврежденной.

Это безопасно:

// guaranteed by the spec to be safe
request.getSession().setAttribute("foo", 1);

Это не безопасно:

HttpSession session = request.getSession();
Integer n = (Integer) session.getAttribute("foo");
// not thread safe
// another thread might be have got stale value between get and set
session.setAttribute("foo", (n == null) ? 1 : n + 1);

Это не гарантированно безопасно:

// no guarantee that same instance will be returned,
// nor that session will lock on "this"
HttpSession session = request.getSession();
synchronized (session) {
  Integer n = (Integer) session.getAttribute("foo");
  session.setAttribute("foo", (n == null) ? 1 : n + 1);
}

Я видел, как этот последний подход поддерживается (в том числе в книгах J2EE), но он не гарантированно работает по спецификации сервлета. Вы можете использовать идентификатор сеанса для создания мьютекса , но должен быть лучший подход.

Нет.И поскольку вы не хотите, чтобы один и тот же клиент (с сеансом) выполнял параллельные запросы, вы должны сериализовать эти запросы следующим образом Абстрактный контроллер делает ли это весной MVC

В некотором смысле это зависит от дизайна вашего клиента.

Есть ли в вашем веб-дизайне возможность для одного клиента иметь несколько ожидающих запросов одновременно, используя один и тот же сеанс HTTP? Это кажется трудным, если вы не привязываете один HTTP-сеанс к нескольким сокетам. (aka, AJAX) Если не делать этого, HTTP-доступ данного клиента будет однопоточным, если речь идет о сервере, что означает, что отдельный сеанс является поточно-безопасным.

Синхронизация объектов вашего сеанса сделает приложение более защищенным от будущих изменений, которые сделают ваше веб-приложение способным иметь несколько одновременных запросов, так что это неплохая идея. В современных реализациях Java синхронизация не требует больших затрат, которые ранее были связаны с ней, особенно когда синхронизация обычно не выполняется. Если ваше приложение использует AJAX, что подразумевает, что вы ожидаете множественные одновременные запросы в полете к вашему веб-серверу, синхронизация является обязательной.

Это не так, но в большинстве случаев ваши клиенты будут получать к ним доступ только с одного потока.

У разных клиентов будут разные потоки, и у каждого будет свой собственный сеанс.

Как указывает Эдди, одна из ситуаций, когда вы можете столкнуться с двумя потоками, обращающимися к одному и тому же сеансу, - два вызова ajax пытаются изменить один и тот же атрибут сеанса. В противном случае у вас не будет проблем.

Сеанс не является поточно-ориентированным, и ни методы get, ни set не гарантированно являются поточно-ориентированными. В общем случае в контейнере сервлетов вы должны предполагать, что находитесь в многопоточной среде, и никакие инструменты не являются безопасными.

Это также относится и к объектам, которые вы храните в сеансе. Сам сеанс не будет манипулировать сохраненным объектом, но вы можете извлечь объект в другом потоке и попытаться манипулировать им. Вы должны проверить свой собственный код, чтобы увидеть, возможны ли условия гонки.

Пример кода, который вы опубликовали, действителен, но проблема может существовать за пределами вашего примера. Это гарантирует отсутствие условий при настройке сеанса, но ничто не мешает другому потоку переопределить набор. Если код в вашем запросе зависит от значения, оставшегося неизменным, у вас все еще могут быть проблемы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top