繁体   English   中英

javax.servlet.ServletContext set / getAttribute是否安全?

[英]Is javax.servlet.ServletContext set/getAttribute thread safe?

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

servlet规范3.0声明:

servlet可以通过名称将对象属性绑定到上下文中。 绑定到上下文中的任何属性都可用于属于同一Web应用程序的任何其他servlet。

但是,没有关于这些操作的并发行为的信息。 查看Apache Tomcat的源代码 ,可以看出它是作为ConcurrentHashMap实现的,从而使其有效地保证了线程安全。

我的问题是,我是否应该始终将这些操作视为不是线程安全的,并让应用程序处理同步,或者是否有一些我缺少的信息?

你可以放心地假设你可以调用getAttribute和setAttribute而不需要同步任何东西,但是你应该让你存储的对象成为线程安全的(最简单的方法是存储不可变的东西)。 注释中链接的问题是关于在servletContext中存储可变对象,在这种情况下,使用它的线程需要首先获取其锁定( 接受的答案解释)。

没有拼写要求。 Java Concurrency in Practice ,第4.5.1节解释模糊文档中介绍了这一点:

你将不得不猜测。 提高猜测质量的一种方法是从实施它的人(例如容器或数据库供应商)的角度解释规范,而不是仅仅使用它的人。 Servlet总是从容器管理的线程调用,可以安全地假设如果有多个这样的线程,容器就知道这一点。 servlet容器使某些对象可以为多个servlet提供服务,例如HttpSession或ServletContext。 因此,servlet容器应该期望同时访问这些对象,因为它已经创建了多个线程并且从它们调用了Servlet.service等方法,这些方法可以合理地期望访问ServletContext。

由于无法想象这些对象有用的单线程上下文,因此必须假设它们已经成为线程安全的,即使规范没有明确要求这样做。 此外,如果他们需要客户端锁定,客户端代码应该在什么锁上同步? 文档没有说,猜测似乎很荒谬。 规范和官方教程中的示例进一步证明了这种“合理的假设”,这些示例展示了如何访问ServletContext或HttpSession并且不使用任何客户端同步。

另一方面,使用setAttribute放置在ServletContext或HttpSession中的对象由Web应用程序拥有,而不是servlet容器。 servlet规范没有提出任何协调对共享属性的并发访问的机制。 因此,容器代表Web应用程序存储的属性应该是线程安全的或有效的不可变的。 如果所有容器都代表Web应用程序存储了这些属性,那么另一个选择是确保从servlet应用程序代码访问时它们始终被锁定保护。 但是因为容器可能想要在HttpSession中序列化对象以进行复制或钝化,并且servlet容器不可能知道你的锁定协议,所以你应该让它们成为线程安全的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM