为什么Servlet中的实例变量不是线程安全的

时间:2012-04-21 18:03:49

标签: java servlets java-ee thread-safety instance-variables

当我阅读Head First Servlet and JSP时,他们说实例变量是非线程安全的。

我不太理解这句话。例如:我有一个名为ActionServlet.java的servlet。每次将每个用户的请求发送到服务器,容器将创建一个新线程并创建新的ActionServlet实例。

ActionServlet可能有一个结构:

public class ActionServlet extends HttpServlet {
   // example of instance variable
   Instance variable;
   public void processRequest(HttpServletRequest request, HttpServletResponse response) {   
       // process something relating to instance variable
   }
}

因此,因为所有这些线程都为ActionServlet创建了一个新的类实例,所以我在这里看不到任何问题。因为这些线程的实例是彼此分开的。

请在多线程环境中找出使用实例变量时的问题。

谢谢:)

3 个答案:

答案 0 :(得分:16)

你犯的错误就在这里:

  

所以,因为所有这些线程都为它创建了一个新的类实例   ActionServlet,所以我在这里看不到任何问题。因为实例   这些线程是彼此分开的。

容器不会为每个请求创建Servlet类的新实例。它重用了现有的一个。这就是为什么它们不是线程安全的。

Stripes Action Framework为每个请求创建一个新实例,这样在该框架下就可以了。但是,例如,Struts 1遵循Servlet模型,并不会为每个请求创建新操作。

这并不意味着容器仅限于单个实例,理论上它可以创建多个实例,但它不是指定的行为,因此不能依赖它。大多数流行的都没有。

答案 1 :(得分:3)

  

因为所有这些线程都创建了一个新的类实例(action.java),所以我没有看到任何问题

您假设每个线程都创建一个仅由该线程使用的类实例,这就是您没有任何问题的原因。

但是,尝试用您的特定示例想象从两个线程访问相同的实例。如果两者同时使用requestresponse成员,会发生什么? 也许您会从无法识别的请求中读取数据,并且您将编写一个混合了两个部分的不一致响应。

所以在你的情况下,实例变量也不是线程安全的,因为如果两个线程访问同一个实例,它们会相互干扰。

答案 2 :(得分:0)

问题是,你的action.java总是没有实例化,但它是从实例池获取的,对于请求线程也是如此,它们是从线程池中获取的,因此可以共享一个servlet实例通过多个请求。