Publishing attributes via ServletContext#setAttribute is thread-safe! This can be derived from the Java Servlet Specification, chapter 4.5: (…) Any attribute bound into a context is available to any other servlet that is part of the same Web application.(…).
(Reason: Making objects available to other servlets means also to make them available to other threads. This is only possible, if proper synchronization is used, so synchronization is mandatory for ServletContext#setAttribute).
So the same is also true for reading published attributes via ServletContext#getAttribute.
Note
But if an object like a HashMap is shared between different threads, the developer must ensure that this shared object itself is accessed in a proper, thread-safe way! Using a ConcurrentHashMap is a possible solution, but does not solve the race condition when the attribute is initialized, as the null check will not be atomic.
ConcurrentMap<String, Object> shared = (...)servletContext.getAttribute("sharedData"); if (shared == null) { shared = new ConcurrentHashMap<>(); servletContext.setAttribute("sharedData", shared); }