3

Вопрос по данному коду :

1.Насколько я знаю Servlet Container отвечает за потокобезопасность сервлетов.

2.Но сушествует вариант что несмотря на это может возникнуть проблема с потокобезопасностью как например в данном коде.

Мой вопрос заключается в том: почему при данном коде переменная counter считается не потокобезопасной ?

package threadSafety;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import java.math.*;
public class SimpleServlet extends HttpServlet
{
//A variable that is NOT thread-safe!
private int counter = 0;
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
doPost(req, resp);
}
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
resp.getWriter().println("<HTML><BODY>");
resp.getWriter().println(this + ": <br>");
for (int c = 0; c < 10; c++)
{
  resp.getWriter().println("Counter = " + counter + "<BR>");
  try
  {
    Thread.currentThread().sleep((long) Math.random() * 1000);
    counter++;
  }
  catch (InterruptedException exc) { }
}
resp.getWriter().println("</BODY></HTML>");
}
}
etki
  • 36,151
  • 1
    контейнер не обеспечивает потокобезопасность – etki Jul 13 '16 at 22:04
  • @Etki - Можеш дать ссылку на нормальный материал по этой теме ? http://www.javaworld.com/article/2072798/java-web-development/write-thread-safe-servlets.html Из написанного тут я понял что да обеспечивает. – Maks.Burkov Jul 13 '16 at 22:07
  • Контейнер отвечает за потокобезопасный вызов методов сервлета, но дальше что происходит внутри этих методов (т.е. в вашем коде) его уже не интересует. Как вы себе вообще представляете, что контейнер будет магически превращать весь ваш потоко-небезопасный код в потокобезопасный? – Roman Jul 13 '16 at 22:47
  • Так если контейнер отвечает за потокобезопасный вызов методов сервлета то значит каждый метод сервлета синхронизированный так ? Если объявить общую переменную в сервлете то потокобезопасность ее не касается ? Ответ @Etki был таким - контейнер не обеспечивает потокобезопасность.. Абсолютно не понятно что происходит. Если есть у кого подробное описание процесса - буду рад!!!!! – Maks.Burkov Jul 13 '16 at 23:26

1 Answers1

4

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

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

Отвечая на ваши вопросы:

1.Насколько я знаю Servlet Container отвечает за потокобезопасность сервлетов.

Для порожденных вами потоков - нет.

2.Но сушествует вариант что несмотря на это может возникнуть проблема с потокобезопасностью как например в данном коде.

Так как переменная у вас уровня экземпляра, а контейнер создает на каждый сервлет только один экземпляр его класса(https://java.net/downloads/servlet-spec/Final/servlet-3_1-final.pdf - глава 2, параграф 2.2), то и эта переменная будет общая для всех запросов и соответственно модифицировать ее могут несколько запросов одновременно.

  • http://www.javaworld.com/article/2072798/java-web-development/write-thread-safe-servlets.html Пример взят из этой статьи. Посмотри. Там описывается что да. – Maks.Burkov Jul 14 '16 at 00:19
  • @Maks.Burkov, извиняюсь проглядел что переменная не локальная. Сейчас поправлю ответ. – Mikhailov Valentin Jul 14 '16 at 00:34
  • В таком случае разве нельзя синхронизировать саму переменную ? Например поместив ее в синхронизированный метод или использовать volatile ? – Maks.Burkov Jul 14 '16 at 00:46
  • @Maks.Burkov, что бы не быть многословным посоветую вам почитать - Java Concurrency in Practice там про все кроме новинок очень хорошо написано. И гляньте книги вот из этого списка http://ru.stackoverflow.com/questions/416634. – Mikhailov Valentin Jul 14 '16 at 07:18
  • Спасибо посмотрю! – Maks.Burkov Jul 14 '16 at 12:45