11

可能重复:
servlet 是如何工作的?实例化、会话变量和多线程

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

4

1 回答 1

32

你的问题归结为:是从同一个对象线程安全的多个线程调用一个方法。答案是:这取决于. 如果您的对象(让它成为 servlet)是无状态的或只有final字段,那么这是完全线程安全的。局部变量和参数是线程本地的(位于堆栈上,而不是堆上)。

此外,每个调用都会收到一个不同的andservice()实例。然而,这里是一个不安全的 servlet 的例子:ServletRequestServletResponse

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是不够的):

synchronized(this) {
    ++counter;
}

AtomicInteger

private AtomicInteger counter = new AtomicInteger();

//...
counter.incrementAndGet();

在这种特殊情况下AtomicInteger要好得多,因为它使用 CAS CPU 操作是无锁的,而synchronized它是互斥体。

于 2012-07-14T16:47:17.180 回答