Servlet的生命周期是由Servlet容器来负责的。
Servlet容器通常采用单实例多线程的方式,减少Servlet创建实例的开销,提高效率。
当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类(如果设置了on-start-up,启动时就会实例化)。当又有新的客户端请求该servlet时,一般不会再次实例化该servlet类,也就是有多个线程在同时使用这个servlet实例。
因此,当有两个或多个线程同时访问一个Servlet时,可能会发生多个线程同时访问同一资源的问题。
Servlet的线程安全问题主要是由于Servlet实例变量使用不当导致的,例如:
public MyServlet extends HttpServlet{
实例变量 output;
public void service(ServletRequest request, ServletResponse){
局部变量 username;
... ...
对实例变量output的操作; // 可能导致同步问题
... ...
对局部变量username的操作; // 不会导致同步问题
... ...
}
}
Servlet实例的JMM(Java Memory Model)模型:
根据JMM,系统存在一个主内存,Java中所有实例变量都存储在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存,工作内存由缓存和堆栈组成:缓存中保存的主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量,线程之间无法相互直接访问堆栈中的变量。