[Java] Deadlock 데드락
데드락에 대해 관심을 가지게 된 계기는 MQTT 클라이언트를 구현하면서였다.
MQTT 클라이언트를 org.eclipse.paho.client.mqttv3.MqttClient로 구현하고
MqttClient의 setCallback 메소드에 MqttCallback 인터페이스를 익명 클래스로 구현하여 파라미터로 넣었다.
데드락이 발생한 원인은 바로 이 MqttCallback 인터페이스의 messageArrived 메소드에 있었다.
messageArrived 메소드의 설명은 다음과 같다.
void messageArrived(java.lang.String topic, MqttMessage message) throws java.lang.Exception
This method is called when a message arrives from the server.
This method is invoked synchronously by the MQTT client. An acknowledgment is not sent back to the server until this method returns cleanly.
If an implementation of this method throws an Exception, then the client will be shut down. When the client is next re-connected, any QoS 1 or 2 messages will be redelivered by the server.
Any additional messages which arrive while an implementation of this method is running, will build up in memory, and will then back up on the network.
If an application needs to persist data, then it should ensure the data is persisted prior to returning from this method, as after returning from this method, the message is considered to have been delivered, and will not be reproducible.
It is possible to send a new message within an implementation of this callback (for example, a response to this message), but the implementation must not disconnect the client, as it will be impossible to send an acknowledgment for the message being processed, and a deadlock will occur.
Parameters:topic - name of the topic on the message was published tomessage - the actual message.Throws:java.lang.Exception - if a terminal error has occurred, and the client should be shut down.
첫 번째 밑줄 : 구현 메소드가 예외를 던졌을 때, 해당 클라이언트가 셧다운된다.
사실 이 내용은 본 게시물의 주제인 데드락과는 관련이 없다. 그럼에도 밑줄을 친 이유는 클라이언트의 접속이 끊어질 때 로그로는 오류의 원인을 알 수 없기 때문에(로그로 접속이 끊어진 사유는 나오지 않고, Connection lost와 같이 나온다.) 접속이 끊어지는 이유 중 하나일 수 있다는 것을 누군가가 보기를 바라는 마음으로 밑줄을 쳤다.
두 번째 밑줄 : 메소드 구현 시 클라이언트가 반드시 접속 상태여야 한다. 접속 상태가 아니라면 메세지가 처리될 때 ACK을 보내는 것이 불가능하고, 데드락이 발생하기 때문이다.
MQTT 전반을 구현하며 가장 애를 먹였던 두 오류의 원인이 위 두 오류이다. 두 오류 모두 로그나 디버깅으로 확인하는데는 한계가 있었고, API 문서에 있었다.
상기된 MqttClient 클래스나 MqttCallback 인터페이스에 대해서는 다른 게시물에서 다루도록 하고, 이제 본격적으로 데드락에 대해 알아보자.
사실 데드락에서 가장 중요한 것은 데드락을 찾아내는 것이다. 참고로 데드락을 검색할 때는 java deadlock debugging으로 검색하기보다는 java deadlock detection으로 찾는 것이 좋다.
codedelay.com/how-to-detect-and-avoid-deadlock-in-java-with-example/