我最近遇到的最困难的调试问题是异步操作之间的死锁。例如,给定两个CompletionStage
链,其中第一个链调用依赖于第二个链完成的方法,第二个链调用依赖于第一个链完成的方法。它在现实生活中并不明显,因为依赖性往往被隐藏,有时死锁涉及三方以上。
部分问题在于无法找出CompletableStage
正在等待的内容。这是因为操作引用CompletableStage
,而不是相反。
现在大多数调试器提供了一定程度的死锁检测,但这仅适用于线程。 如何在CompletableStage链之间调试死锁?
答案 0 :(得分:0)
我最终做了以下事情:
在每个javascript if class x contains z get link of class y
链的末尾,安排一个在超时后被触发的事件:
CompletionStage
如果舞台按预期完成,请使用Set<Object> knownDeadlocks = ConcurrentHashMap.newKeySet();
// ...
Future<?> deadlockListener = scope.getScheduler().schedule(() ->
{
if (knownDeadlocks.add(Throwables.getStackTraceAsString(context)))
log.warn("Possible deadlock", context);
}, DEADLOCK_DURATION.toMillis(), TimeUnit.MILLISECONDS);
禁用deadlockListener:
CompletionStage.handle()
为了完整起见,您还有:
return stage.handle((value, throwable) ->
{
// WARNING: By design, CompletionStage.whenComplete() suppresses any exceptions thrown by its argument, so we use handle() instead.
deadlockListener.cancel(false);
if (throwable == null)
return value;
return rethrowException(throwable);
});