【问题标题】:Stateless objects are always thread-safe?无状态对象总是线程安全的?
【发布时间】:2015-09-28 03:34:17
【问题描述】:

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

【问题讨论】:

    标签: java multithreading concurrency


    【解决方案1】:

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

    【讨论】:

    • 我想这是有道理的,但他们会用这个作为例子似乎令人困惑——因为调用StatelessFactorization 方法可能会导致一些不是线程安全的事情。使用原始(或任何不可变)参数对我来说不会那么混乱。
    • @bcorso,我想本书作者想展示一些接近现实世界的例子。虽然,当然,我不能准确地说。
    【解决方案2】:

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

    这是一个令人困惑的例子,因为您不能假设您总是可以在该方法中修改您想要的任何内容,并且所有内容都将神奇地成为线程安全的。然而,这是一个有趣的示例,它通常由实际应用程序中的多个线程执行。

    【讨论】:

    • 感谢您提供额外的上下文!
    猜你喜欢
    • 1970-01-01
    • 2011-10-14
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多