Безопасна ли HttpSession для потоков? Являются ли операции установки/получения атрибутов потокобезопасными?
На StackOverflow.com может быть уместно представить проблему следующим образом:
Вопрос: Необходима ли потокобезопасность объекта, хранимого в сессии?
Я хотел бы разобраться в вопросе потокобезопасности объектов, которые устанавливаются в сессии в контексте многопоточного доступа. Должен ли объект, который я сохраняю в сессии, быть потокобезопасным, чтобы можно было гарантировать, что состояние этого объекта будет известным и корректным?
Кроме того, я наткнулся на некоторые рекомендации в интернете, согласно которым можно использовать следующий код:
synchronized(session) {
session.setAttribute("abc", "abc");
}
Является ли это действительно валидным подходом для обеспечения потокобезопасности при работе с сессиями?
Такое описание подчеркивает суть проблемы и ставит конкретные вопросы, что соответствует стилю вопросов на StackOverflow.
3 ответ(ов)
В определенном смысле это зависит от дизайна вашего клиента.
Есть ли у вас возможность в веб-дизайне, чтобы один клиент мог выполнять несколько одновременно ожидающих запросов, используя одну и ту же HTTP-сессию? Это кажется сложным, если только вы не связываете одну HTTP-сессию с несколькими сокетами (то есть AJAX). В противном случае HTTP-доступ для данного клиента будет однопоточным с точки зрения сервера, что означает, что одна сессия в значительной степени безопасна для потоков.
Синхронизация ваших объектов сессии сделает приложение более безопасным в отношении будущих изменений, которые могут сделать ваше веб-приложение способным обрабатывать несколько одновременно выполняющихся запросов, поэтому это неплохая идея. В современных реализациях Java синхронизация больше не имеет тех больших затрат, которые были раньше связаны с ней, особенно когда синхронизация в большинстве случаев не оспаривается. Если ваше приложение использует AJAX, что подразумевает ожидание нескольких одновременно выполняющихся запросов к вашему веб-серверу, то синхронизация становится необходимой.
Нет, они не являются таковыми, но в большинстве случаев ваши клиенты будут обращаться к ним только с использованием одного потока.
У разных клиентов будут разные потоки, и каждый из них будет иметь свою собственную сессию.
Как указывает Эдди, ситуация, в которой вы можете столкнуться с двумя потоками, обращающимися к одной и той же сессии, возникает, когда два AJAX-запроса пытаются изменить один и тот же атрибут сессии. В противном случае проблем быть не должно.
Сессия не является потокобезопасной, и методы get и set не гарантируют безопасность при работе с потоками. В общем случае в контейнере сервлетов следует считать, что вы работаете в многопоточной среде, и никакие предоставленные инструменты не являются безопасными.
Это также касается объектов, которые вы храните в сессии. Сама сессия не будет манипулировать хранимыми объектами, однако вы можете получить доступ к объекту из разных потоков и попытаться его изменить. Вам нужно самостоятельно проверить ваш код на наличие возможных условий гонки.
Представленный вами пример кода валиден, но проблема может выходить за пределы вашего примера. Он гарантирует, что не возникнут конфликты при записи в сессию, но ничего не мешает другому потоку переопределить это значение. Если ваш код зависит от того, что значение останется неизменным, вы все равно можете столкнуться с проблемами.
Что значит 'synchronized'?
В чем разница между использованием synchronized на lockObject и использованием this как блокировки?
Почему нет ConcurrentHashSet, если есть ConcurrentHashMap?
Как объявить массив в одну строку?
Какие проблемы следует учитывать при переопределении equals и hashCode в Java?