JAVAEE_Servlet_18_关于Servlet线程安全问题
关于Servlet线程安全问题
-
Servlet线程安全
-
Servlet 是单实例多线程的环境下运行的。
在服务器运行期间,一个Servlet接口实现类,只能创建一个实例对象(一个进程(Servlet接口实现类的实例对象) 对应 多个线程(用户请求),无论有多少个用户请求来访问该Servlet实例对象,都只是访问的同一
个Servlet实例对象), 在服务器关闭的时候,会将所有创建的Servlet实现类的实例对象销毁。 -
什么时候会出现线程安全问题?
1.多线程并发执行
2.存在共享数据
3.共享数据有修改操作。
-
分析在JVM虚拟机中哪些数据可能会存在线程安全问题,而哪些数据不会存在线程安全问题 ?
1.首先局部变量不存在线程安全问题,因为局部变量在栈中存储,一个线程一个栈,这样每个线程的栈内存中都有自己的局部变量,所以局部变量内存空间不共享,也就不存在线程安全问题。 2.常量不会被修改所以常量不存在线程安全问题。 3.所有线程共享一个堆。 - 堆内存中存储了Java对象。(new出来的java对象在堆中存储) - 对象中的实例变量是多线程共享的。当多线程并发操作,共同访问实例变量,并且涉及到修改操作的时候,就存在线程安全问题。(因为堆内存是多线程共享的,而存储在堆内存中的对象也就是共享的,对象中的实例变量也就是被共享的) 4.所有线程共享一个方法区。 - 方法区中的静态变量也是多线程共享的,当多线程并发操作,共同访问,并且涉及到修改操作静态变量的时候,也会存在线程安全问题。 5.线程安全问题不只存在JVM中,也存在数据库中,例如:多线程同时修改一张表。 - 解决方案: 5.1 在java程序中使用synchronized关键字,让线程排队执行。 5.2 行级锁(悲观锁) 5.3 事务隔离级别 5.5 乐观锁
6.怎么解决Servlet的线程安全问题?
解决方案: 6.1 不使用实例变量,尝试使用局部变量 String username=request.getParameter("username"); 6.2 若必须使用实例变量,那么考虑将该对象变成多例对象,一个线程一个java对象,这样实例变量的内存也不会共享了。 6.3 若必须使用单例对象,那就只能使用synchronized线程同步机制,但是线程一旦排队执行,那么降低了吞吐量。用户体验下降。 synchronized(this) { username=request.getParameter("username"); response.getWriter().print("Congratulation "+username+" register success!!!"); }
-