Servlet线程安全的解决方法

Servlet体系结构是创建在Java多线程机制之上的,它的生命周期是由Web容器负责的。web

当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,通常不会再实例化该Servlet类,也就是有多个线程在使用这个实例。缓存

这样的话,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的状况,数据可能会变得不一致,因此就很容易形成一系列的一些安全性问题。安全

解决此类的方法也有多多线程

一、实现 SingleThreadModel 接口并发

该接口指定了系统如何处理对同一个Servlet的调用。若是一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,固然也就不存在线程安全的问题。这种方法只要继承这个接口就好了性能

public class XXXXX extends HttpServlet implements SingleThreadModel {  
    …………  
}

二、同步对共享数据的操做测试

使用synchronized 关键字能保证一次只有一个线程能够访问被保护的区段,在本论文中能够经过同步块操做来保证Servlet的线程安全。同步后的代码以下:this

Public class XXXXXX extends HttpServlet {  

    synchronized (this){XXXX}  
     
    } 
}

三、避免使用实例变量线程

线程安全问题还有些是由实例变量形成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。设计

对上面的三种方法进行测试,能够代表用它们都能设计出线程安全的Servlet程序。可是,若是一个Servlet实现了SingleThreadModel接口,Servlet引擎将为每一个新的请求建立一个单独的Servlet实例,这将引发大量的系统开销。SingleThreadModel在Servlet2.4中已再也不提倡使用;一样若是在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大降低。这是由于被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量下降,并且不少客户处于阻塞状态。另外为保证主存内容和线程的工做内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。因此在实际的开发中也应避免或最小化Servlet 中的同步代码;在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也能够知道,方法中的临时变量是在栈上分配空间,并且每一个线程都有本身私有的栈空间,因此它们不会影响线程的安全。

小结

Servlet的线程安全问题只有在大量的并发访问时才会显现出来,而且很难发现,所以在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量形成的,所以在Servlet中应避免使用实例变量。若是应用程序设计没法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。

相关文章
相关标签/搜索