容器本身已经提供了多线程的支持,为我们省下了并发方面的编码,但是并发通常会带来线程安全的问题,我们来讨论一下安全的问题。
先了解一个概念,属性:属性不同于parameter,它存在于request,session,context中,是以键值对儿的形式存在的,获取之后的值为object。

context中的线程安全。
其中的属性是非线程安全的,比如有两个servlet,A,B。
A中有如下代码:

这时页面上应该展示的为22,42,但是同时B中的代码为:
getServletContext().setAttribute("bar", "16");
在A执行到sleep的过程中,执行Bservlet就会发现结果变为22,16。这样就展示了线程的不安全。
处理方式:
因为是不同servelt的线程都能造成不安全,因此在servlet的方法service方法上使用synchronized关键字都是不能解决问题的,只能提升到context的高度来解决问题。


就能够安全了

Session的线程安全
与context类似,也会存在不安全的问题,需要加入synchronized(session)就可以了。

Servlet的线程安全。
可能会有两个线程访问同一个servlet的情况,这样就会出现实例变量线程不安全的情况,如下:
i为一个实例变量。
i++;
try {
    Thread.sleep(5000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println("=========================" + i);

这里如果同时有两个客户端访问同一个servlet的时候就会出现问题。
为了解决这个问题,可以使用如下的办法。

  • 实现SingleThreadModel接口,这样就能保证只能有一个线程访问servlet。但是就不能够并发了,影响效率。
  • 尽量使用临时变量,因为临时变量是存储在栈中的,而每一个线程都有一个独立的栈,所以不会有线程安全的问题。
  • request的属性也是线程安全的。
  • 使用synchronized (this) {}代码块包住就可以了。
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐