在Singleton会话Bean中管理并发访问



我与一位同事讨论了单例会话bean中的并发管理。根据我的理解,在阅读了Oracle文档之后,如果去掉@ConcurrencyManagement注释,那么它默认为容器管理的并发。在文档中,它说明了以下关于容器管理的单例会话bean的内容:

javax.ejb.Lock注释和javax.ejb.LockType类型用于指定singleton的业务方法或@Timeout方法的访问级别。

如果singleton类上不存在@Lock注释,则默认的锁类型@Lock(LockType.WRITE)将应用于所有业务和超时方法。

现在,如果您使用@ConcurrencyManagement(ConcurrencyManagementType.BEAN)对bean进行注释,那么您有责任确保使用synchronized关键字和其他标准Java并发特性在所有客户端上同步bean的状态。文章甚至说:

使用bean管理的并发创建singleton的开发人员被允许使用Java编程语言同步原语,如同步和volatile,以防止在并发访问过程中出错。

我在关于容器管理并发的章节中没有看到这一点,这让我相信,如果你想自己同步,你需要用@ConcurrencyManagement(ConcurrencyManagementType.BEAN)来注释类。

当我的同事在我的豆子上看到这个注释时,他评论说"伙计,你们做了一些奇怪的事情",这引发了这次讨论。

他的bean都没有任何@ConcurrencyManagement注释,但他在整个类中使用了synchronized关键字。我说他使用的任何细粒度同步都是毫无意义的,因为他的所有业务方法都有一个隐含的@Lock(LockType.WRITE)注释,这是对的吗?这意味着,如果一个客户端调用他的一个方法,那么没有其他客户端可以调用bean的任何方法,因此该方法内的显式同步将是无用的。

例如,对于他的一个业务方法中synchronized (myLock)中使用的某个锁myLock,由于方法本身是有效同步的,因此不会对该锁产生争用。

如果我错了,请纠正我,但他的方法看起来基本上是这样的:

public synchronized void myMethod() {
    // do stuff
    synchronized (lock) {
        // modify mutable state
    }
}
public synchronized void myOtherMethod() {
    // do other stuff
    synchronized (lock) {
        // modify mutable state
    }
}

假设在这个单例会话bean中创建lock只是为了保护bean中的可变状态,那么在使用容器管理的并发性时,它似乎没有任何作用。

提前感谢您对此的任何见解!

一般来说,您的所有期望都是正确的。有一个小情况,您的同事的代码实际上可以使用同步原语。

如果存在ejb-jar.xml文件,它可以将并发管理设置为由bean管理。它看起来像这样:

<enterprise-beans>
    <session>
        <ejb-name>MySingletonEJB</ejb-name>
        <ejb-class>com.blah.MySingletonEJB</ejb-class>
        <transaction-type>Bean</transaction-type>
        ...
    </session>
...
</enterprise-beans>

自从EJB 3以来,这确实是一种糟糕的做法,而且注释肯定是首选,因为配置与源代码是正确的。

你是对的,但这取决于他锁定的是什么,如果对象只绑定到那个单例,那么他确实是一个无所不知的人,因为双重锁定,他实际上放慢了程序的执行速度。

最新更新