1、Servlet是单实例多线程环境下运行的。
2、什么时候程序存在线程安全问题?
- 多线程并发
- 有共享的数据
- 共享数据有修改操作
3、在JVM中,哪些数据可能会存在线程安全问题?
-局部变量内存空间不共享,一个线程一个栈,局部变量在栈中存储,局部变量不会存在线程安全问题
-常量不会被修改,所以常里不会存在线程安全问题
-所有线程共享一个堆
- 堆内存中new出来的对像在其中存储,对象内部有“实例变量”,所以实例变量”的内存多线程是共享的。
- 实例变量多线程共同访问,并且涉及到修改操作的时候就会存在线程安全问题。
-所有线程共享一个方法区
- 方法区中有静态变量,静态变里的内存也是共享的,若涉及到修改操作,静态变里也存在线程安全问题。
4、线程安全问题不止是体现在JVM中,还有可能发生在数据库中
例:多个线程共享同一张表,并且同时去修改表中一些记录, 那么这些记录就存在线程安全问题,怎么解决数据库表中数据的线程安全问题呢?至少有两种方案:
第一种方案是:在java程序中使用synchronized关键字,线程排队执行,自然不会在数据库中并发,解决线程安全问题。
第二种方案是:行级锁[悲观锁]
第三种方案是:事务隔离级别,例如:串行化
第四种方案是:乐观锁
5、怎么解决线程安全问题?
(1) 不使用实例变量,尽里使用局部安量
(2) 若必须使用实例变里,那么我们可以考虑将该对象变成多例对象,一个线程一个java对象, 实例变量的内存也不会共享。
(3) 若必须使用单例,那就只能使用synchronized线程同步机制,线程-旦排队执行,则吞吐量降低,降低用户体验。
6、Servlet怎么解决线程安全问题?
(1) 不使用实例变量,尽里使用局部变量
(2) Servlet必须是单例的,所以剩下的方式只能考虑使用synchronized,线程同步机制。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Servlet线程安全问题</title>
</head>
<body>
<form action="/defence/ThreadServlet" method="post">
用户名:
<input type="text" name="username"/>
<input type="submit" value="注册">
</form>
</body>
</html>
package com.ning.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/ThreadServlet")
public class ThreadServlet extends HttpServlet {
//实例变量
//private String username;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
//局部变量(调用一次方法创建一块内存,不会出现线程问题)
String username = request.getParameter("username");
out.print("恭喜你"+username+"注册成功");
//实例变量(会出现安全线程问题)
// username = request.getParameter("username");
// out.print("恭喜你"+username+"注册成功");
//使用实例变量安全线程问题解决措施
// synchronized (this) {
// username = request.getParameter("username");
// out.print("‘恭喜你”+username+“注册成功");
// }
}
}
左边先请求的是User右边后请求的是刘三,结果如下: