Как я могу убедиться, что мое веб-приложение сервлетов java является потокобезопасным? Что мне нужно делать в отношении переменных сеанса, статических переменных класса или чего-либо еще, что может быть проблемой безопасности потоков?
В Java, как я могу убедиться, что мое веб-приложение является потокобезопасным?
Ответ 1
Факт: существует только один экземпляр сервлета в жизни webapp. Он создается при запуске webapp, и он уничтожается при завершении webapp. Также см. этот ответ для грубой интерпретации.
Таким образом, он был разделен между всеми запросами (потоками). Если вы присваиваете данные с запросом или сессией в виде экземпляра (или, что еще хуже, как static
), то он определенно не является потокобезопасным, поскольку затем он был распределен между всеми запросами (потоками) из всех пользователей (сеансов) по всей стране. Вам просто нужно назначить их как локальные переменные метода, чтобы сохранить их потокобезопасными. Итак:
public class MyServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
Это в основном все, что вам нужно учитывать при разработке сервлетов с учетом потоков.
Затем есть сеанс (HttpSession
) атрибуты, которые могут быть разделены между несколькими запросами одного и того же пользователя, но в реальном мире вы на самом деле не нужно беспокоиться о синхронизации доступа к сеансу. Обычно вы размещаете там только пользовательские данные, такие как зарегистрированный пользователь, пользовательские настройки, корзина покупок и т.д. Вам просто нужно убедиться, что вы не помещаете данные с ограниченным запросом запроса в область сеанса. Он будет отображаться в нескольких окнах/вкладках браузера внутри одного сеанса.
Тогда есть приложения (ServletContext
) атрибуты, которые распределяются между всеми пользователями по всей стране, но вы обычно ставите только константы и другие статические данные, такие как конфигурация webapp, DAO factory, содержимое списка вниз и т.д. Это все, кстати, можно сделать с помощью ServletContextListener
, также см. этот ответ для базового примера. Вам просто нужно убедиться, что вы не добавляете чистые данные с запросом или сеансом в область приложения.
Ответ 2
- не использовать переменные экземпляра сервлетов и фильтров
- не использовать статические переменные
- прочитайте эту статью о безопасности потоков сеансов
- думаю,
Ответ 3
Ничего себе, это загруженный вопрос.
Проще говоря, вам необходимо обеспечить тщательную синхронизацию доступа к любым общим данным. Например, вы можете синхронизировать доступ к статической переменной с помощью мьютекса или синхронизированной функции.
Обратите внимание, что вам также может потребоваться синхронизация на более высоких уровнях, если вам нужны атомарные транзакции, которые одновременно изменяют несколько общих ресурсов.
Проектирование параллельного приложения не простое, и нет волшебной пули (к сожалению). Я настоятельно рекомендую книгу " Java Concurrency in Practice" для получения дополнительной информации о написании безопасного параллельного кода.
Ответ 4
Вы имеете в виду в контексте, в отличие от любого другого приложения Java? Там действительно не так много. Каждый запрос сервлета заставляет контейнер выдавать новый поток для его обработки, поэтому переменные экземпляра в сервлете должны быть потокобезопасными. Лучше обрабатывать весь ваш бизнес с помощью локальных переменных в методах doGet/doPost(). Есть одна мысль, о которой я могу думать. С переменными сеанса может случиться так, что у пользователя открываются два окна браузера, указывающие на ваше приложение. В этом случае вам нужно будет следить за безопасностью потоков с помощью области сеанса.