关于java:关于servlet的线程安全性

Regarding thread safety of servlet

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How do servlets work? Instantiation, session variables and multithreading

servlet是线程安全的吗?例如,如果我打开5个不同的浏览器并向容器中的一个servlet发送请求,它是否仍然是线程安全的,我特别指service()方法


您的问题可以归结为:正在从同一对象线程安全的多个线程调用一个方法。答案是:视情况而定。如果您的对象(让它成为servlet)是无状态的,或者只有final字段,那么这是完全线程安全的。局部变量和参数是线程的局部变量(驻留在堆栈上,而不是堆上)。

另外,每个service()调用都会收到ServletRequestServletResponse的不同实例。但是,下面是一个不安全servlet的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class UnsafeServlet implements Servlet {

    private int counter;

    public void init(ServletConfig config) throws ServletException {
    }

    public void service(ServletRequest request, ServletResponse response)
        ++counter;
    }

    public void destroy() {
    }

}

由于多个线程可以访问counter变量,因此必须以某种方式保护它:要么使用synchronized(volatile是不够的):

1
2
3
synchronized(this) {
    ++counter;
}

AtomicInteger

1
2
3
4
private AtomicInteger counter = new AtomicInteger();

//...
counter.incrementAndGet();

在这种情况下,AtomicInteger要好得多,因为它使用cas-cpu操作是无锁的,而synchronized是互斥的。