我们都知道servlet是多线程的,同时一个servlet实现类只会有一个实例对象,也就是它是Singleton的,所以多个线程是可能会访问同一个servlet实例对象的。
当Tomcat接收到Client的HTTP请求时,Tomcat从线程池中取出一个线程,之后找到该请求对应的Servlet对象并进行初始化,之后调用service()方法。要注意的是每一个Servlet对象再Tomcat容器中只有一个实例对象,即是单例模式。如果多个HTTP请求请求的是同一个Servlet,那么着两个HTTP请求对应的线程将并发调用Servlet的service()方法。
上图中的Thread1和Thread2调用了同一个Servlet1,所以此时如果Servlet1中定义了实例变量或静态变量,那么可能会发生线程安全问题(因为所有的线程都可能使用这些变量)。
多线程和单线程Servlet具体区别:多线程下每个线程对局部变量都会有自己的一份copy,这样对局部变量的修改只会影响到自己的copy而不会对别的线程产生影响,线程安全的。但是对于实例变量来说,由于servlet在Tomcat中是以单例模式存在的,所有的线程共享实例变量。多个线程对共享资源的访问就造成了线程不安全问题。