8

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

我不是很理解这个说法。例如:我有一个名为ActionServlet.java. 每次,每个用户的请求都会发送到服务器,容器会创建一个新线程并创建新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,所以我在这里看不到任何问题。因为这些线程的实例是相互独立的。

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

谢谢 :)

4

3 回答 3

17

你犯的错误在这里:

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

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

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

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

于 2012-04-21T18:10:15.923 回答
3

因为所有这些线程都创建了一个新的类实例(action.java),所以我看不出有什么问题

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

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

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

于 2012-04-21T18:10:21.693 回答
0

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

于 2012-04-21T18:09:24.503 回答