为什么Servlet不是线程安全的?

Why Servlets are not thread Safe?

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

我需要知道为什么servlet不是线程安全的?在Struts2.0框架控制器中,servlet线程安全的原因是什么?


I need to know why the servlets are not thread safe ?

Servlet实例本质上不是线程安全的,因为Java编程语言一般具有多线程特性。Java虚拟机支持通过多个线程执行相同的代码。对于具有多个处理器的机器来说,这是一个很大的性能优势。这还允许多个并发用户执行相同的代码,而不会相互阻塞。

设想一个拥有4个处理器的服务器,其中一个普通的servlet可以每秒处理1000个请求。如果这个servlet是线程安全的,那么Web应用程序的行为就好像它运行在一个拥有1个处理器的服务器上,其中servlet每秒只能处理250个请求(好吧,这并不完全是这样的,但是你知道了)。

如果在使用servlet时遇到线程安全问题,那么这是您的错误,而不是Java或Servlet的错误。您需要修复servlet代码,这样就不会将请求或会话范围的数据分配为servlet的实例变量。有关深入的解释,请参见servlet如何工作?实例化、会话、共享变量和多线程。

And whats the reason that in Struts 2.0 framework controller servlet is thread safe ?

它不是线程安全的。您将Struts Dispatcherservletfilter与Struts actions混淆。Struts操作在每个请求上都被重新创建。所以每个请求都有自己的请求范围struts操作实例。Struts Dispatcherservletfilter不将它们存储为自己的实例变量。相反,它将其存储为EDOCX1的一个属性(0)。


servlet是普通的Java类,因此不是线程安全的。

但是,如果没有实例变量,Java类是线程安全的。只有实例变量需要同步。(实例变量是在类中声明的变量,而不是在其方法中声明的变量。

方法中声明的变量是线程安全的,因为每个线程创建自己的程序堆栈,函数变量在堆栈中分配。这意味着方法中的变量是为每个线程创建的,因此没有任何关联的线程同步问题。

方法变量是线程安全的,类变量不是。


每个servlet映射只有一个servlet实例;所有实例属性在所有请求之间共享。访问这些属性必须考虑到这一点。

struts 2个动作(不是"控制器servlet",它们既不是servlet也不是控制器)在每个请求中被实例化。操作属性只能由单个请求的线程访问。


servlet不是线程安全的,但是我们可以通过将servlet类实现到SingleThreadModel中,使其成为线程安全的。像下面给出的类定义一样,但是性能问题仍然存在,所以更好的选择是使用同步部分。

1
2
3
4
5
6
public class SurveyServlet extends HttpServlet
                           implements SingleThreadModel
{
servlet code here..
...
}

servlet通常是多线程的。

Servlet容器通常通过为每个请求创建一个新的Java线程来管理并发请求。新线程被赋予对请求的servlet的对象引用,后者通过同一线程发出响应。这就是为什么在编写servlet时设计并发性很重要的原因,因为同一个servlet实例可以处理多个请求。

servlet容器处理servlet请求的方式取决于实现;它们可以使用单个servlet,也可以使用servlet池,这取决于供应商的系统架构。

Struts2动作对象是为每个请求实例化的,因此没有线程安全问题。


servlet本身不是线程安全的。通过使服务方法同步,可以使其线程安全。您需要实现singleThreadInterface以使其线程安全。