【问题标题】:Detailed Thread-Safety Questions concerning Java Servlets有关 Java Servlet 的详细线程安全问题
【发布时间】:2012-08-19 20:00:51
【问题描述】:

我目前必须使特定的 Java servlet 实现线程安全。 代码不是我写的,我也没有参与它的设计或任何事情。我“只是”必须使它成为线程安全的:)

我不是线程安全的初学者,但也不是专业人士。 Servlet 对我来说(或多或少)是全新的。我已经完成了一些教程并且了解了有关 servlet 的基础知识,但仅此而已。我能找到的所有关于使 servlet 线程安全的教程都相当肤浅,我仍然有一些未解决的问题,我似乎无法找到答案。一些帮助将不胜感激。

1.) 据我了解,HttpServletRequests 和 HttpServletResponses 不在不同线程之间共享,因此我不需要同步它们的读写访问(这是正确的吗?)。但是 HttpServletRequestWrappers 等呢?

2.) 我必须同步对 getServletContext() 返回的 ServletContext 对象的访问,特别是如果我在其上使用 setAttribute(),对吧?

3.) HttpServletRequests 有一个 getCookies() 方法。这些 Cookie 是否可能在不同的请求之间共享,或者每个请求都有自己的 Cookie 对象(即使它们代表相同的“真实”cookie)?换种方式问:我是否必须同步对返回的 cookie 对象的访问?

感谢您花时间阅读我的问题。我期待着你的回答:)

【问题讨论】:

    标签: java servlets thread-safety


    【解决方案1】:

    Servlet 不是线程安全的,因为应用程序服务器可以维护 Servlet 的单个实例或实例池,并在多个传入请求之间共享它们。因此,servlet 不应该有任何状态(即 servlet 对象级变量不是线程安全的)。 Servlet 规范以前有 SingleThreadModel 接口来强制给定的 servlet 是线程安全的,但我猜自 2.3 以来已被弃用。

    回复:

    1. 没错,这些是 doGet 和 doPost 等 HTTP 方法的参数,因此无需同步对这些方法的访问。

    2. 正确,因为 getServletContext() 返回一个上下文级对象,所有 servlet 和运行给定 servlet 的所有线程都可以访问该对象。

    3. 每个请求都带有自己的一组 cookie。同样,这是从方法参数 HttpServletRequest 中获得的,因此访问不需要同步。

    【讨论】:

      【解决方案2】:

      当您使 servlet 线程安全时,您很少需要同步。 Servlet 从一开始也应该是线程安全的,因为单个 Servlet 实例可能被多个用户使用。此外,您不能相信只有一个 servlet 实例,除非您的 servlet 容器指定始终只有一个。

      1) 处理请求和响应对象时不需要同步,因为一次只有一个线程可以处理一个请求。

      2) 您应该尝试以一种无需在 servlet 内的 ServletContext 中设置任何值的方式来设计您的应用程序。通常 ServletContext 在启动时被初始化,然后被 servlet 或过滤器用作只读。我不确定它是否应该是线程安全的,但是如果你在同一个请求中设置多个值,那么无论如何你都必须同步,这样读取这些值的 servlet 就不会被弄乱。但这是基本的线程安全问题,与 servlet 无关。

      3) cookie 不需要同步,因为它们处理当前请求并且只有一个线程可以完成。

      新的 servlet 容器支持异步模型,其中多个线程可能处理一个请求,但一次仍然是一个线程。

      【讨论】:

        【解决方案3】:
        1. 您的理解是正确的。实际上线程是为每个请求创建的。所以HttpServletRequestHttpServletResponse 是线程本地的。所以没有分享这两个。您不需要同步它们。 HttpServletRequestWrapperHttpServletResponseWrapper 是分别提供HttpServletRequestHttpServletResponse 接口的方便实现的类。您无需在同步上下文中担心它们。

        2. 当然,您必须为ServletContext object returned by getServletContext() 提供同步,因为它在您的应用程序中的 servlet 之间共享。

        3. 因为HttpServletRequest 是容器为服务请求而创建的线程的本地线程。因此 cookie 也是该线程本地的,并且不共享。因此无需为 cookie 提供同步。

        几个概念:

        1. Servlet 在您的应用程序中始终是单例的。即只创建一个对象。
        2. 为每个请求创建一个不同的线程(实际上是从线程池中获得的)。以下内容是线程本地的:HttpServletRequestHttpServletResponse

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-14
          • 1970-01-01
          • 2021-12-16
          • 1970-01-01
          • 2018-04-08
          • 2016-08-24
          • 2012-02-10
          • 2012-07-14
          相关资源
          最近更新 更多