javaweb之Servlet线程安全问题

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右边后请求的是刘三,结果如下:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值