同步中的Thread.notify()上的IllegalMonitorStateException

时间:2015-04-18 02:38:14

标签: java android multithreading

这是在Android应用中。我们有一个类来管理与服务器的套接字通信,并且该类具有用于发送和接收消息的线程。 我们偶尔会在方法中获得IllegalMonitorStateException,然后将消息发送给处理程序,然后通知发送线程'这样它就会从处理程序读取消息并将其发送到服务器:

java.lang.IllegalMonitorStateException: object not locked by thread before notify()
at java.lang.Object.notify(Native Method)
at com.company.appname.package.ServerConnection.sendMessageToServer(ServerConnection.java:448)
at com.company.appname.package.ServerConnection.sendMessageToServer(ServerConnection.java:418)
at com.company.appname.package.ServerConnection.gotResponse(ServerConnection.java:403)
at com.company.appname.package.ServerConnection.gotConnected(ServerConnection.java:349)
at com.company.appname.package.ServerEventHandler.handleMessage(ServerEventHandler.java:59)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)

异常发生在以下代码中的mMessageSendThreadForServer.notify();

public class MessageSendThread extends Thread {
    ...
}

public class ServerConnection {
    ...
    private final Object mMessageSendThreadForServerLock = new Object();
    private MessageSendThread mMessageSendThreadForServer;
    ...
    private void sendMessageToForServer(String msg) 
    {
        ...
        // Wake the sending thread
        synchronized(mMessageSendThreadForServerLock) 
        {
            synchronized(mMessageSendThreadForServer) 
            {
                mMessageSendThreadForServer.notify();
            }
        }
    }
    ...
}

我发现的所有文档和其他问题都表明这不应该导致IllegalMonitorStateException。我已经看到很多问题,人们在synchronize内更改了对象,但我们在synchronize内所做的只是调用notify()

任何想法都表示赞赏。我很难过。

1 个答案:

答案 0 :(得分:2)

您提供的代码段没有任何问题,但可以修改它以防止它。

试试这个片段,看看会发生什么。它可以防止另一个线程更改引用。

...
// Wake the sending thread
synchronized(mMessageSendThreadForServerLock) 
  final MessageSendThread sendThread = mMessageSendThreadForServer;
  synchronized(sendThread) 
  {
    sendThread.notify();
  }
}
...