YARN-6376 fixes timelinewriter.flush() race condition among concurrent putEntities() calls and periodical flush by TimelineCollectorManager by synchronizing on the writer object.
Synchronizing on the writer is still a little brittle there, because there is a getWriter method which lets callers access the writer without synchronizing on it. AppLevelTimelineCollector#AppLevelAggregator#agregate() does this in line 152: getWriter().write(...) In this case it doesn't flush, but if that were to be added, that would re-introduce the race fixed in
Instead of exposing the writer, perhaps it would be better to have the sub-classes call #putEntities instead. It defers to the private writeTimelineEntities which does the same work to get the context:
TimelineCollectorContext context = getTimelineEntityContext();