原视频地址:https://www.bilibili.com/video/BV1vb41187jH?p=44
Servlet是单实例多线程环境下运行的。
什么时候程序存在线程安全问题
- 多线程并发
- 有共享数据
- 共享数据有修改操作
在JVM中,哪些数据可能会存在线程安全问题
- 局部变量内存空间不共享,一个线程一个栈,局部变量在栈中存储,局部变量不会存在线程安全问题
- 常量不会被修改,所以常量不存在线程安全问题
- 所有线程共享一个堆
- 堆内存中new出来的对象在其中存储,对象内部有“实例变量”,所以“实例变量”的内存是多线程共享的。实例变量多线程共同访问,并且涉及到修改操作的时候,就会存在线程安全问题。
- 所有线程共享一个方法区
- 方法区中有静态变量,静态变量的内存是共享的,若涉及到修改操作,静态变量也存在线程安全问题
线程安全问题不止是体现在JVM中,还有可能发生在数据库中,例如:多个线程共享同一张表,并且同时去修改表中的一些记录,那么这些记录就存在线程安全问题
解决方案
- 第一种:在java程序中使用synchronized关键字,线程排队执行
- 第二种:行级锁【悲观锁】
- 第三种:事务隔离级别,例如:串行化
- 第四种:乐观锁
怎么解决线程安全问题?
- 不使用实例变量,尽量使用局部变量
- 若必须使用实例变量,那么可以考虑将该对象变成多例对象,一个线程一个java对象,实例变量的内存也不会共享
- 若必须使用单例,那就只能使用synchronized线程同步机制,线程一旦排队执行,则吞吐量降低,用户体验下降。
Servlet怎么解决线程安全问题
【1】不使用实例变量,尽量使用局部变量
【2】Servlet必须是单例的,所以剩下的方式只能考虑synchronized线程同步机制