Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the issue with "Long monitor contention event"

I have the following service code where I launch a thread responsible for dispatching messages are they come in.

       public void run() {
          while (! Thread.interrupted()) {
            try {
              Message msg = null;
              synchronized (_queue) {
                if (_queue.size() == 0) {
                  _queue.wait(10000);
                }

                if (_queue.size() != 0) {
                  msg = _queue.poll();
                }

                if (msg != null) {
                  _dispatcher.dispatch(msg);
                }
              }
            }
            catch (InterruptedException i) {                }
            catch (Exception e) {                }
          }
      }
  public void add (final Message m){
    if (m == null)
      return;
    synchronized (_queue){
      _queue.add(m);
      _queue.notify();
    }
  }

But when this code runs on my android simulator, I get a lot of warnings like the following:

Long monitor contention event with owner method=void com.foo.PrioritizedMessageQueue.run() from PrioritizedMessageQueue.java:58 waiters=0 for 585ms

To me, this seems like the most efficient way of writing a queue processor. When there are not message to process, the processing thread will wait until one is added, and the "add" will notify any waiting thread why a new message is added to the queue. My thought is the dispatching thread won't use minimal resources when no message exists (as it is blocked).

However, there is a reason why android is issuing this warning but I wonder why. It is clearly not happy with my thread being blocked this long but why is that an issue? Isn't this more efficient in that it won't use any CPU cycles while it's waiting?

Also, should I be worried that android may kill my thread because it's been blocked too long? I would hate for my thread to be killed but not the service. If my service is killed, I can handle that, but I can't handle just that one thread being killed.

like image 276
T. Francis Avatar asked Oct 17 '22 18:10

T. Francis


1 Answers

You should release the lock on the queue before calling _dispatcher.dispatch. Otherwise, the outside thread attempting to call _queue.add is blocked while the worker thread is processing the message.

Adjusting the curly braces is all that's needed. Here's your run thread function adjusted to allow for dispatch to be called after relinquishing the monitor of _queue.

   public void run() {
      while (! Thread.interrupted()) {
        try {
          Message msg = null;
          synchronized (_queue) {     // acquire the queue lock
            if (_queue.size() == 0) {
              _queue.wait(10000);
            }

            if (_queue.size() != 0) {
              msg = _queue.poll();
            }
          }                           // release the queue lock

          if (msg != null) {
            _dispatcher.dispatch(msg);
          }
        }
        catch (InterruptedException i) {
        }
        catch (Exception e) {
        }
      }
  }
like image 106
selbie Avatar answered Nov 15 '22 06:11

selbie