Is javax.servlet.ServletContext set/getAttribute t

2020-02-06 07:10发布

Having to use setAttribute() and getAttribute(String) in javax.servlet.ServletContext, I cannot find any information on the intended behavoir with concurrent access. However, these operations may very well be called by different threads.

The servlet specification 3.0 states:

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.

However, there is no information on concurrency behavior of these operations. A look into the source code of Apache Tomcat reveals that it is implemented as a ConcurrentHashMap, thus making it effectively thread-safe.

My question is, should I always treat these operations as not thread-safe and have the application handle the synchronisation, or is there a piece of information that I am missing?

1条回答
家丑人穷心不美
2楼-- · 2020-02-06 07:54

You can safely assume you can call getAttribute and setAttribute without synchronizing on anything, but you should make the objects you store there threadsafe (the easiest way being to store things that are immutable). The question linked in the comments is about storing a mutable object in the servletContext, in which case threads using it need to acquire its lock first (which the accepted answer explains).

There's not a spelled-out requirement. This is covered in Java Concurrency in Practice, section 4.5.1 Interpreting Vague Documentation:

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.

查看更多
登录 后发表回答