我有2个线程在运行。一个用于网络事件,另一个用于程序逻辑。由于需要同步,因此使用Java ReetrantLock类。
网络线程工作流程:
-接收消息
-等待锁(myLock.lock())
-将消息传递到逻辑线程
-释放锁(myLock.unlock())
逻辑线程工作流程:
-运行某些系统
-等待锁(myLock.lock())
-运行2个在try catch块内处理网络消息的系统(我们将此阶段称为 A )
-最终释放锁(myLock.unlock)
通过这种配置,程序可以在95%的时间正常运行,但是有时会挂起,因此我启动了VisualVM试图了解问题的根源,然后得到了以下
您可以看到网络线程被锁定,因为它正在等待逻辑线程释放可重入锁(这是预期的)。但是由于某种原因,逻辑线程被卡在打印stackstrace吗?我无法理解如何从这种情况陷入僵局(陷入阶段 A )。
我也尝试使用JProfiler,并且得到了相同的结果。我应该相信我从这些探查器(stacktrace挂起)中看到的内容吗?
顺便说一下,这里是程序似乎挂起的相关代码:
public void handle(EntityDeletionMessage message) {
try {
Entity toRemove = mapGameState.getEntityById(message.getEntityId());
mapGameState.removeEntity(toRemove);
} catch (EntityNotFoundException e) {
e.printStackTrace(); // From my understanding it freeze here
}
}
在冻结时,控制台上也没有堆栈跟踪
编辑:这是来自两个系统中需要与网络线程同步的代码(显然,它们都具有相同的锁):
系统1:
public void update(float deltaTime) {
lock.lock(); // It will be unlocked in the second system.
// process some network messages.
}
系统2:
public void update(float deltaTime) {
while (networkMessages.size > 0) {
NetworkMessage message = networkMessages.removeFirst();
MessageHandler handler = messageHandlerManager.getHandler(message.getClass());
if (handler == null) {
Gdx.app.error("NetworkMessagesManagerSystem", "No handler for the message: " + message.getClass());
continue;
}
try {
handler.handle(message);
} catch (Exception e) {
e.printStackTrace();
}
}
lock.unlock(); // It was locked in the system 1
}