Publishing attributes via ServletContext#setAttribute thread-oriented! This can be obtained from the Java Servlet Specification, chapter 4.5: (...) Any related attribute in the context is accessible to any other servlet that is part of the same network application. (...).
(Reason: making objects available to other servlets also means making them available to other threads. This is only possible with proper synchronization, so synchronization is required for all servlet containers that implement ServletContext#setAttribute ).
The same applies to reading published attributes through ServletContext#getAttribute .
But, of course, if an object like HashMap is shared between different threads, the developer must make sure that the most common object is accessed in an appropriate, thread-safe way! Using ConcurrentHashMap , as already mentioned in other answers to your question, is a possible solution, but does not solve the race conditions when initializing the attribute, since the null check will not be atomic:
ConcurrentMap<String, Object> shared = (...)servletContext.getAttribute("sharedData"); if (shared == null) { shared = new ConcurrentHashMap<>(); servletContext.setAttribute("sharedData", shared); }
Therefore, ServletContextListener can be used to initialize the context when starting the web application!
Change: To avoid confusion
From the Java Servlet Specification, we can conclude that sharing attributes between servlets through ServletContext#setAttribute and ServletContext#getAttribute really thread-oriented.
But no matter how it is implemented internally, set/getAttribute can guarantee only the correct publication, it cannot guarantee the correct synchronization if the common attribute is a mutable object that is modified after sharing. This is technically impossible!
Example:
// servlet 1: Person p = new Person("Keith", "Richards"); context.setAttribute('key', p); // share p p.setName("Ron", "Wood"); // modification AFTER sharing // servlet 2 (some time LATER): Person p = context.getAttribute(); // now, p is guaranteed to be non-null, // but if class Person is not thread-safe by itself, it may be any of // - "Keith Richards" // - "Keith Wood" // - "Ron Richards" // - "Ron Wood" // (depending on the implementation of setName, it may be even worse!)
As a result, each value of the servlet context attribute must be
- immutable (through end fields) or effectively immutable, OR
- mutable, but never mutated after sharing, OR
- implemented in a thread-oriented manner (e.g. synchronized)
(This is true for all kinds of objects shared by threads in Java, not only in relation to servlet context attributes)