servlet是否存在线程安全问题

        今天老师问了一句,servlet存在线程安全问题吗,心想着servlet不是单例的嘛,每个线程在调用的时候都会为实例对象分配独立的引用。我就以为servlet属于线程安全的。晚上自己再网上查看了一下,发现servlet不是安全的。

        下面就给大家介绍一下servlet线程安全问题

        首先,默认的servlet是非线程安全的,servlet是单例模式,只产生一个实例,根据项目中web.xml实例,这个实例是web容器产生的,比如Tomcat,JBOSS,weblogic等。

        就是说多个客户请求产生多个线程,一个线程对应一个客户,但是用的servlet对象却是一个。既然用的对象是一个,那么实例变量就是共享数据了,说到共享数据还不同步,必然是非线程安全的。

        比如说两人同时在12306上买票,这时很不巧只剩下一张票,甲乙在同一时间点击购票,两人同时都到购票了,你们说到时候上车怎么办?

有这个例子可以看到servlet线程是不安全的,当对一个复杂对象进行某种操作时,从操作开始到操作结束,被操作的对象往往会经历若干非法的中间状态。调用一个函数(假设该函数是正确的)操作某对象常常会使该对象暂时陷入不可用的状态(通常称为不稳定状态),等到操作完全结束,该对象才会重新回到完全可用的状态。如果其他线程企图访问一个处于不可用状态的对象,该对象将不能正确响应从而产生无法预料的结果,如何避免这种情况发生是线程安全性的核心问题。

这是我在网上找的实例,自己运行了一下显示的结果,

public class threadSafe extends HttpServlet{
    private static final long serialVersionUID = 1L;
    private volatile int num = 0;
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        addOne();
        response.getWriter().write("now access num : " + getNum());
    }
    /**

     * 读取开销低

     */

    private int getNum() {
        return num;
    }
    /**

     * 其写入为非线程安全的,赋值操作开销高

     */

    private synchronized void addOne() {
        num ++;
    }
}

在两个浏览器上不停地访问这个地址,显示的结果没有出现多个线程共同的数字,



为什么没有出错的,咱们在这里加入了

synchronized关键字

synchronized关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、D等)正在用这个方法,若有则要等正在使用synchronized方法的线程B(或者C、D)运行完这个方法后再运行此线程A,若没有则直接运行。

常见的线程安全的解决办法: 

1.使用方法内局部变量 
是因为各线程有自己堆栈空间,存储局部变量 
方法参数传入,多采用传值(volue copy)传入方法内 

2.对操作共享资源的语句,方法,对象, 使用同步 
比如写入磁盘文件,采用同步锁,但建议尽量用同步代码块,不要用同步方法 


3.使用同步的集合类 
使用Vector代替ArrayList 
使用Hashtable代替HashMap。 

4.不要在 Servlet中再创建自己的线程来完成某个功能。 
Servlet本身就是多线程的,在Servlet中再创建线程,将导致执行情况复杂化

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

double_lifly

点喜欢就是最好的打赏!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值