ServletContext对象的线程安全性

Lin*_*nus 7 java servlets java-ee

我在我的ServletContext中存储了一个HashMap对象.但是多个请求线程正在读取和修改此HashMap.

因为我相信ServletContext对象是在请求线程之间共享的,我是否需要同步对此HashMap的访问?或者还有其他更好的方法来实现同样的目标吗?

isn*_*bad 16

通过ServletContext#setAttribute线程安全发布属性!这可以从Java Servlet规范第4.5章得出:( ...)绑定到上下文的任何属性都可用于属于同一Web应用程序的任何其他servlet.(...).

(原因:使对象可用于其他servlet也意味着它们可供其他线程使用.这是唯一可能的,如果使用了正确的同步,则必须进行同步ServletContext#setAttribute).

因此,通过阅读已发布的属性也是如此ServletContext#getAttribute.

但是当然如果像a之类的对象HashMap在不同的线程之间共享,开发人员必须确保以正确的,线程安全的方式访问这个共享对象本身!使用ConcurrentHashMap正如您在问题的其他答案中所述的那样,是一种可能的解决方案,但在初始化属性时不能解决竞争条件,因为null检查不是原子的:

ConcurrentMap<String, Object> shared = (...)servletContext.getAttribute("sharedData");
if (shared == null) {
    shared = new ConcurrentHashMap<>();
    servletContext.setAttribute("sharedData", shared);
}
Run Code Online (Sandbox Code Playgroud)

因此,a ServletContextListener可用于在Web应用程序启动时初始化上下文!