【问题标题】:Java EE beans and volatile keywordJava EE bean 和 volatile 关键字
【发布时间】:2016-02-23 22:30:21
【问题描述】:

Java EE 规范的Servlet、EJB 和CDI 部分描述了bean 管理(注入等)。但是规范也没有(显式或隐式地)描述 bean 容器的并发属性。如果我使用过 WildFly 或 GlassFish,那么 Java EE 应用服务器可以从一个线程中访问更多的 bean 对象。

所以问题是,我是否必须对所有 bean 字段使用 volatile 关键字,理论上可以从多个线程访问(即对于几乎所有 bean,并且至少对于所有带有 @ 注释的字段) 987654322@)?

【问题讨论】:

    标签: jakarta-ee ejb javabeans cdi volatile


    【解决方案1】:

    技术答案取决于 bean 的种类和属性的种类,但通常您根本不需要担心这一点。

    对于 EJB,容器已经实施了一些默认的并发控制,您可以通过 @Lock@ConcurrencyManagement 注释进行控制。另见 a.o. EJB @Asynchronous to retrieve real time inserted row in JSF seems to be thread locked.

    对于 JPA 实体,任何对并发控制的需求都表明存在主要的设计/基本问题。并发控制应该只在控制器中执行,而不是模型或视图。 JPA 实体本身绝不代表“控制器”。换句话说,JPA 实体中的 volatile 字段没有任何意义,而托管 bean 中引用 JPA 实体本身的 volatile 字段可能有意义。

    在托管 bean (JSF/CDI) 的情况下,通常如果您担心某些托管 bean 的并发性,那么 bean 的范围很可能是错误的,需要缩小范围。例如。使用@ViewScoped@ConversationScoped 而不是@SessionScoped 甚至@ApplicationScoped。另见 a.o. How to choose the right bean scope?

    如果是应用程序范围的 bean(“singletons”in widest sense),这可能是有意义的,但前提是对于感兴趣的字段不存在并发/原子包装类,例如 ConcurrentMapAtomicBoolean,等等。另见 a.o. Concurrency of @ApplicationScoped JSF managed beans.

    【讨论】:

    • 比如我的jsf-web-application使用ajax请求,所以它们(AJAX请求)本质上是异步的,一次浏览器客户端的视图可以有很多请求到服务器.我可以假设服务器将响应来自一个线程的查询吗?
    • > “在 EJB 的情况下,容器已经实施了一些默认的并发控制,您可以通过 Lock 和 ConcurrencyManagement 注释来控制”。在这种情况下,容器如何解决可见性问题?当一个线程构造bean并注入依赖,而另一个线程调用可以访问注入字段的方法时,JVM不保证存储在非易失性字段中的实际引用对其他线程可见。
    • JSF ajax 故事在最后一段的最后一个链接中详细说明和子链接。对于 EJB,它们作为代理注入,引用实例池而不是实际实例。另见 a.o. *.com/q/25514361 对于 CDI 托管 bean 也是如此(但对于 JSF 托管 bean 则不然;但是不可能将范围更窄的 JSF 托管 bean 注入到范围更广的 JSF 托管 bean 中,这样就排除了潜在的并发问题)。我的回答中的第一段仍然存在:通常你不需要担心这一切。