无状态对象始终是线程安全的?

时间:2015-09-28 03:34:18

标签: java multithreading concurrency

Java Concurrency In Practice, Section 2.1中,它声明:

  

无状态对象始终是线程安全的。

并以下面的课程为例:

@ThreadSafe
public class StatelessFactorization implements Servlet {
    public void service(ServletRequest req, ServletResponse resp){
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        encodeIntoResponse(resp, factors);       // <-- isn't it possible for resp to be
                                                 //     modified by mult. threads at once?
    }
}

问题:

如上面的代码所示,如​​果多个线程试图修改相同的ServletResponse变量会发生什么。

从我对内存分配的理解来看,上面的类似乎并不完全是线程安全的。

虽然对ServletRequestServletResponse的引用放在调用线程的本地堆栈上,但实际的对象存储在堆上 - 它们在所有线程之间共享。

2 个答案:

答案 0 :(得分:5)

此处无状态对象为StatelessFactorization类。它是无状态的,因为它没有自己的状态,即它没有实例字段。因此,该对象是线程安全的。 resp是实现ServletResponse接口的另一个对象,它可能是也可能不是线程安全的。这里没有讨论resp的线程安全性。

答案 1 :(得分:5)

当您发出将由servlet处理的HTTP请求时,将调用其a方法。如果您有多个客户端同时发出多个请求,则每个请求可能由不同的线程处理。但是,每个线程将收到的serviceServletRequest的实例不同,因此您不会让多个线程修改这些对象的相同实例。每个线程都修改它们自己的实例。当然,魔术不会发生这种情况,您的servlet容器(例如Tomcat)是在这种特定情况下处理线程创建和为您分配这些实例的容器。

这是一个令人困惑的例子,因为你无法假设你总是可以在该方法中修改你想要的任何东西,并且一切都将神奇地保证线程安全。但是,它是一个通常由实际应用程序中的多个线程执行的方法的有趣示例。