If list is null here, there is a window between this sync block and the finally sync block where emitting is still true and events are queued and not replayed until a subsequent event appears. A better way would be:

synchronized (this) {
  list = queue;
  queue = null;
  if (list = null) {
    emitting = false;
    break;
  }

But then the finally block should be changed to avoid setting emitting to false.