死锁,EJB 3.1,在 Singleton 中使用异步方法和 TimerService

发布于 2024-09-14 04:53:22 字数 2046 浏览 0 评论 0原文

在我的 Singleton-EJB 中,我每 2 分钟启动一次 TimerService。当客户端访问测试方法时 有时应用程序会陷入死锁。问题是,test 方法调用 EJB 内部的异步方法(请参阅方法defineABC)。当 scheduleMethod 尝试创建单个操作计时器并因此尝试获取锁(因为计时器回调方法用 LOCK.WRITE 注释)时,就会发生死锁。与此同时,我们已经在defineABC方法中尝试调用异步方法asynchMethod。也许调用ejbLocal.asynchMethod(...);也会尝试获取锁。无论如何,我在这里遇到了死锁,因为异步方法从未被调用。那么问题出在哪里呢?

这是一个源代码片段:

@Singleton
@Startup
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class XEJB implements XEJBLocal {

@javax.annotation.Resource(name = "x/XEJB/TimeService")
private TimerService timerService;
@javax.annotation.Resource
private SessionContext ctx;

@Schedule(minute = "*/2", hour = "*", persistent = false)
@Lock(LockType.READ)
private void scheduleMethod() {
    // Create Single Action Timer
    timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
}

@Timeout
@Lock(LockType.WRITE)
private void timer(Timer timer) {
   // Do something
}

@Override
@Lock(LockType.READ)
public B test(...)  {
    return determineABC(...);
}

@Lock(LockType.READ)
private B determineABC(...) {
    XEJBLocal ejb= (XEJBLocal)  ctx.getBusinessObject(ctx.getInvokedBusinessInterface());
    Future<ArrayList> result = null;
    result = ejb.asynchMethod(...);
    result.get(4, TimeUnit.MINUTES);  // Sometimes runs into a DEADLOCK
    ...
}

@Asynchronous
@Override
@Lock(LockType.READ)
public Future<ArrayList> asynchMethod(...) {
    ...
    return new AsyncResult<ArrayList>(abcList);
}

当我只使用 @Schedule 方法而不使用 TimerService 时,也会发生死锁... 当我不使用 Future 对象而是使用 void 作为异步方法的返回类型时,也会发生死锁。

当抛出超时异常时,死锁就解决了。当我用 @AccessTimeout(2000) 注释 timer 方法时,此时异步方法被调用,因此死锁也解决了。

当我使用 Locktype.READ 作为 timer 方法时,不会发生死锁。但为什么?异步方法调用了什么?

In my Singleton-EJB i start a TimerService every 2 minutes. When a client access the test method
sometimes the application runs into a deadlock. The problem is, the test method calls a asynchronous method inside the EJB (see Method determineABC). The deadlock happens when the scheduleMethod tries to create a single action timer and therefore tries to acquire a lock (because hte timer callback method is annotated with LOCK.WRITE). At the same time we are already in the determineABC Method which tries to invoke the asynchronous method asynchMethod. Maybe the call of ejbLocal.asynchMethod(...); also tries to acquire a lock. Anyway here i run into a deadlock, because the asynchronous method is never called. So what is the problem?

Here is a source code snippet:

@Singleton
@Startup
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class XEJB implements XEJBLocal {

@javax.annotation.Resource(name = "x/XEJB/TimeService")
private TimerService timerService;
@javax.annotation.Resource
private SessionContext ctx;

@Schedule(minute = "*/2", hour = "*", persistent = false)
@Lock(LockType.READ)
private void scheduleMethod() {
    // Create Single Action Timer
    timerService.createSingleActionTimer(new Date(), new TimerConfig(null, false));
}

@Timeout
@Lock(LockType.WRITE)
private void timer(Timer timer) {
   // Do something
}

@Override
@Lock(LockType.READ)
public B test(...)  {
    return determineABC(...);
}

@Lock(LockType.READ)
private B determineABC(...) {
    XEJBLocal ejb= (XEJBLocal)  ctx.getBusinessObject(ctx.getInvokedBusinessInterface());
    Future<ArrayList> result = null;
    result = ejb.asynchMethod(...);
    result.get(4, TimeUnit.MINUTES);  // Sometimes runs into a DEADLOCK
    ...
}

@Asynchronous
@Override
@Lock(LockType.READ)
public Future<ArrayList> asynchMethod(...) {
    ...
    return new AsyncResult<ArrayList>(abcList);
}

The Deadlock also happens when i only use the @Schedule Method and no TimerService...
The DeadLock also happens when i do not use a Future Object but void as return type of the asynchronous Method.

When the timeout Exception is thrown the deadlock is solved. When i annotate the timer method with @AccessTimeout(2000) and this time is up the asynchronous method is called and therefore the deadlock is also solved.

When i use Locktype.READ for the timer Method no Deadlock happens. But why? What does the asychronous method call?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぺ禁宫浮华殁 2024-09-21 04:53:22

读锁必须等待写锁完成才能开始工作。当timer()正在运行时,所有其他调用,甚至是READ方法,都将等待。您确定超时发生在 result.get(4, TimeUnit.MINUTES); 中吗?

我认为在到达 result.get(4, TimeUnit.MINUTES); 之前,您可能在 test() 调用中出现访问超时。

READ locks have to wait for WRITE locks to finish before they start their work. When timer() is working all your other invokations, even to READ methods, are going to wait. Are you sure the timeout happens in result.get(4, TimeUnit.MINUTES);?

I think you may be have access timeouts in test() invokation, way before reaching result.get(4, TimeUnit.MINUTES);.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文