@ApplicationScoped JSF 托管 bean 的并发性

Concurrency of @ApplicationScoped JSF managed beans

我正在使用 Mojarra 2.2.12,在我们的项目中我们有一些 @ApplicationScoped beans。例如:

@ManagedBean
@ApplicationScoped
public class AppScopedBean{

    private int commonValueForClients;

    //GET, SET

    public void evalNew(){
        int newCommonVal;
        //Evaluation of the new value, doesn't depend on the commonValueForClients
        commonValueForClients = newCommonVal;
    }
}

我的问题是我们是否应该担心新赋值的可见性?

我在 the spec 中找不到 JSF 基础结构必须同步对 @ApplicationScoped bean 字段的访问。所以,特别是对于 Mojarra 2.2.12,我们应该将字段声明为 volatile 还是显式同步访问它?

JSF 不会 同步任何范围内对托管 bean 的任何访问。

这是你的责任。使用现有的 concurrency/synchronization 包装器作为字段类型,例如 AtomicInteger, ConcurrentHashMap, Collections#synchronizedList() 等。如果不存在此类包装器,则仅将 volatile 作为最后的手段使用。

可变对象的同步在应用程序作用域的bean 中绝对是必要的。例如,如果HashMap,否则你甚至可能冒 (100% CPU). It is less strictly necessary in session scoped beans as they will only be accessed concurrently when the enduser opens multiple HTTP connections on the same session, and this will by default only happen when two physically different browser instances are spawned, but they will in turn by default already not share the session. So it would only happen in case of robots/hackers and it's therefore still strongly recommended to take care of this in session scoped beans as well. It is nearly unnecessary in view scoped beans as ajax requests are by specification 排队的风险,但在 PrimeFaces 中它可以被 <p:ajax async="true"> 关闭,你必须在视图范围 bean 中考虑到这一点出色地。在请求作用域的 bean 中完全没有必要。

如果您碰巧手头有 CDI,您还可以选择使用自定义注释和 CDI 拦截器模仿 EJB 的 @Lock 注释。这在 Stephan Kintelius 的博客中有详细说明:Concurrency control for CDI, coincidentally posted the day before your question. Keep in mind that JSF bean management facility is as per JSF 2.3 deprecated in favor of CDI. See also Backing beans (@ManagedBean) or CDI Beans (@Named)? 如果可以,请转向 CDI 进行 bean 管理。