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

时间:2016-05-13 20:21:48

标签: multithreading java-ee concurrency singleton ejb

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

  

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

  

如果单例类中没有@Lock注释,则默认锁类型@Lock(LockType.WRITE)将应用于所有业务和超时方法。

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

  

使用bean管理并发创建单例的开发人员允许使用Java编程语言同步原语(例如同步和volatile)来防止并发访问期间出现错误。

我没有在容器管理并发部分的任何地方看到这一点,这使我相信如果你想自己同步事物,你需要使用@ConcurrencyManagement(ConcurrencyManagementType.BEAN)注释该类。

我的同事做了一个评论,说“当你在我的豆子上看到这个注释时,你们做了一些奇怪的事情”,这开始了这个讨论。

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

例如,对于其中一个业务方法中myLock中使用的某些锁synchronized (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中的可变状态,似乎在使用容器管理的并发时它没有任何用途。

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

2 个答案:

答案 0 :(得分:1)

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

如果存在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开始,这确实是一种糟糕的做事方式,注释肯定是首选,因为配置与源代码一致。

答案 1 :(得分:0)

你是对的,但这取决于他锁定的内容,如果对象只与那个单身人士绑在一起,那么他确实是一个全知的人,实际上因为双重而减慢了程序的执行速度锁定。