2015-09-28 128 views
4

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的引用放置在调用线程的本地堆栈上,但实际对象存储在堆上 - 它在所有线程之间共享。

回答

5

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

+0

这是有道理的我猜,但它似乎令人困惑,他们会用这个例子 - 因为调用'StatelessFactorization'方法可能会导致不是线程安全的东西。使用原始的(或任何不可变的)参数对我来说会不那么困惑。 – bcorso

+0

@bcorso,我猜这本书的作者想要展示一些接近现实世界的例子。当然,我不能确切地说。 –

3

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

这是一个令人困惑的例子,因为你不能假设你总是可以在该方法内部修改任何你想要的东西,并且所有东西都会神奇般的线程安全。但是,这是一个有趣的方法示例,通常由现实世界中的多个线程执行。

+0

感谢您的额外环境! – bcorso

相关问题