javax.servlet.ServletContext set/getAttribute 线程安全吗?

Is javax.servlet.ServletContext set/getAttribute thread safe?

必须在 javax.servlet.ServletContext 中使用 setAttribute()getAttribute(String),我找不到任何关于并发访问预期行为的信息。然而,这些操作很可能被不同的线程调用。

servlet specification 3.0 状态:

A servlet can bind an object attribute into the context by name. Any attribute bound into a context is available to any other servlet that is part of the same Web application.

但是,没有关于这些操作的并发行为的信息。查看 source code of Apache Tomcat reveals that it is implemented as a ConcurrentHashMap,从而使其有效地成为线程安全的。

我的问题是,我是否应该始终将这些操作视为非线程安全操作并让应用程序处理同步,还是我遗漏了一条信息?

您可以安全地假设您可以调用 getAttribute 和 setAttribute 而无需对任何内容进行同步,但是您应该使存储在那里的对象成为线程安全的(最简单的方法是存储不可变的东西)。评论中链接的问题是关于在 servletContext 中存储一个可变对象,在这种情况下,使用它的线程需要先获取它的锁(the accepted answer 解释)。

没有明确的要求。 Java 实践中的并发性,第 4.5.1 节解释模糊文档:

中对此进行了介绍

You are going to have to guess. One way to improve the quality of your guess is to interpret the specification from the perspective of someone who will implement it (such as a container or database vendor), as opposed to someone who will merely use it. Servlets are always called from a container-managed thread, and it is safe to assume that if there is more than one such thread, the container knows this. The servlet container makes available certain objects that provide service to multiple servlets, such as HttpSession or ServletContext. So the servlet container should expect to have these objects accessed concurrently, since it has created multiple threads and called methods like Servlet.service from them that could reasonably be expected to access the ServletContext.

Since it is impossible to imagine a single-threaded context in which these objects would be useful, one has to assume that they have been made thread-safe, even though the specification does not explicitly require this. Besides, if they required client-side locking, on what lock should the client code synchronize? The documentation doesn't say, and it seems absurd to guess. This “reasonable assumption” is further bolstered by the examples in the specification and official tutorials that show how to access ServletContext or HttpSession and do not use any client-side synchronization.

On the other hand, the objects placed in the ServletContext or HttpSession with setAttribute are owned by the web application, not the servlet container. The servlet specification does not suggest any mechanism for coordinating concurrent access to shared attributes. So attributes stored by the container on behalf of the web application should be thread-safe or effectively immutable. If all the container did was store these attributes on behalf of the web application, another option would be to ensure that they are consistently guarded by a lock when accessed from servlet application code. But because the container may want to serialize objects in the HttpSession for replication or passivation purposes, and the servlet container can't possibly know your locking protocol, you should make them thread-safe.