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

Why instance variable in Servlet is not thread-safe

本问题已经有最佳答案,请猛点这里访问。

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

我不太明白这个说法。例如:我有一个servlet,它的名称是ActionServlet.java。每次将每个用户的请求发送到服务器时,容器都将创建一个新线程并创建新的ActionServlet实例。

ActionServlet可具有以下结构:

1
2
3
4
5
6
7
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创建了一个新的类实例,所以这里我看不到任何问题。因为这些线程的实例是相互独立的。

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

谢谢)


你犯的错误是:

So, because all these threads create a new class instance for
ActionServlet, so I don't see any problem here. because instances of
these thread is separate of each other.

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

Stripes操作框架确实为每个请求创建了一个新的实例,所以在该框架下这是一个不错的假设。但是,例如,struts 1遵循servlet模型,并且不会为每个请求创建新的操作。

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


because all these threads create a new class instance (action.java), so I don't see any problem

您假设每个线程都创建一个类实例,该实例只能由该线程使用,所以您没有任何问题。

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

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


问题是,action.java并不总是实例化的,但它是从实例池中获取的,请求线程也是如此,它们是从线程池中获取的,因此servlet实例可以由多个请求共享。