我与一位同事讨论了单例 session bean 中的并发管理。根据我的理解,在阅读 Oracle documentation 后, 如果您不使用 @ConcurrencyManagement
注释,那么它默认为容器管理的并发。在文档中,它说明了有关容器管理的单例 session bean 的以下内容:
The javax.ejb.Lock annotation and a javax.ejb.LockType type are used to specify the access level of the singleton's business methods or @Timeout methods.
和
If no @Lock annotation is present on the singleton class, the default lock type, @Lock(LockType.WRITE), is applied to all business and timeout methods.
现在,如果您使用
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
注释 bean ,那么您有责任使用 synchronized
确保 bean 的状态在所有客户端之间同步。关键字和其他标准 Java 并发功能。文章甚至说:Developers who create singletons with bean-managed concurrency are allowed to use the Java programming language synchronization primitives, such as synchronization and volatile, to prevent errors during concurrent access.
我在容器管理的并发部分中没有看到这一点,这让我相信如果你想自己同步事物,你需要用
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
注释这个类。 .我的同事在我的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
}
}
假设
lock
在这个单例 session bean 中创建只是为了保护 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 开始,这确实是一种糟糕的做事方式,并且注释绝对是首选,因为配置与源代码正确。
关于multithreading - 在单例 session Bean 中管理并发访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37218794/