SPARK-2638 MapOutputTracker concurrency improvement

Spark-2638 Improve concurrency of fetching Map outputs

This issue was noticed while perusing the MapOutputTracker source code. Notice that the synchronization is on the containing "fetching" collection - which makes ALL fetches wait if any fetch were occurring.
The fix is to synchronize instead on the shuffleId (interned as a string to ensure JVM wide visibility).

For further details please refer to the JIRA.
The read/write operation of `fetching` should use the same monitor according to the java memory model.

> In addition, using the monitor of an object from outside to synchronized makes it hard to analyse the codes because the monitor of this object may be used (or used in the future) in other place and the developer may not notice somebody has already used it here.

Also this problem looks hard to solve.