Index: trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 13121)
+++ trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 13136)
@@ -107,5 +107,5 @@
      * @param other existing GPX data
      */
-    public void mergeFrom(GpxData other) {
+    public synchronized void mergeFrom(GpxData other) {
         if (storageFile == null && other.storageFile != null) {
             storageFile = other.storageFile;
@@ -125,7 +125,7 @@
             }
         }
-        other.getTracks().forEach(this::addTrack);
-        other.getRoutes().forEach(this::addRoute);
-        other.getWaypoints().forEach(this::addWaypoint);
+        other.privateTracks.forEach(this::addTrack);
+        other.privateRoutes.forEach(this::addRoute);
+        other.privateWaypoints.forEach(this::addWaypoint);
         dataSources.addAll(other.dataSources);
         fireInvalidate();
@@ -136,5 +136,5 @@
      * @return The tracks.
      */
-    public Collection<GpxTrack> getTracks() {
+    public synchronized Collection<GpxTrack> getTracks() {
         return Collections.unmodifiableCollection(privateTracks);
     }
@@ -145,5 +145,5 @@
      * @since 12156
      */
-    public void addTrack(GpxTrack track) {
+    public synchronized void addTrack(GpxTrack track) {
         if (privateTracks.stream().anyMatch(t -> t == track)) {
             throw new IllegalArgumentException(MessageFormat.format("The track was already added to this data: {0}", track));
@@ -159,5 +159,5 @@
      * @since 12156
      */
-    public void removeTrack(GpxTrack track) {
+    public synchronized void removeTrack(GpxTrack track) {
         if (!privateTracks.removeIf(t -> t == track)) {
             throw new IllegalArgumentException(MessageFormat.format("The track was not in this data: {0}", track));
@@ -172,5 +172,5 @@
      * @since 12156
      */
-    public Collection<GpxRoute> getRoutes() {
+    public synchronized Collection<GpxRoute> getRoutes() {
         return Collections.unmodifiableCollection(privateRoutes);
     }
@@ -181,5 +181,5 @@
      * @since 12156
      */
-    public void addRoute(GpxRoute route) {
+    public synchronized void addRoute(GpxRoute route) {
         if (privateRoutes.stream().anyMatch(r -> r == route)) {
             throw new IllegalArgumentException(MessageFormat.format("The route was already added to this data: {0}", route));
@@ -194,5 +194,5 @@
      * @since 12156
      */
-    public void removeRoute(GpxRoute route) {
+    public synchronized void removeRoute(GpxRoute route) {
         if (!privateRoutes.removeIf(r -> r == route)) {
             throw new IllegalArgumentException(MessageFormat.format("The route was not in this data: {0}", route));
@@ -206,5 +206,5 @@
      * @since 12156
      */
-    public Collection<WayPoint> getWaypoints() {
+    public synchronized Collection<WayPoint> getWaypoints() {
         return Collections.unmodifiableCollection(privateWaypoints);
     }
@@ -215,5 +215,5 @@
      * @since 12156
      */
-    public void addWaypoint(WayPoint waypoint) {
+    public synchronized void addWaypoint(WayPoint waypoint) {
         if (privateWaypoints.stream().anyMatch(w -> w == waypoint)) {
             throw new IllegalArgumentException(MessageFormat.format("The route was already added to this data: {0}", waypoint));
@@ -228,5 +228,5 @@
      * @since 12156
      */
-    public void removeWaypoint(WayPoint waypoint) {
+    public synchronized void removeWaypoint(WayPoint waypoint) {
         if (!privateWaypoints.removeIf(w -> w == waypoint)) {
             throw new IllegalArgumentException(MessageFormat.format("The route was not in this data: {0}", waypoint));
@@ -239,5 +239,5 @@
      * @return {@code true} if this GPX data has track points, {@code false} otherwise
      */
-    public boolean hasTrackPoints() {
+    public synchronized boolean hasTrackPoints() {
         return getTrackPoints().findAny().isPresent();
     }
@@ -251,5 +251,5 @@
      * @since 12156
      */
-    public Stream<WayPoint> getTrackPoints() {
+    public synchronized Stream<WayPoint> getTrackPoints() {
         return getTracks().stream().flatMap(trk -> trk.getSegments().stream()).flatMap(trkseg -> trkseg.getWayPoints().stream());
     }
@@ -259,6 +259,6 @@
      * @return {@code true} if this GPX data has route points, {@code false} otherwise
      */
-    public boolean hasRoutePoints() {
-        return getRoutes().stream().anyMatch(rte -> !rte.routePoints.isEmpty());
+    public synchronized boolean hasRoutePoints() {
+        return privateRoutes.stream().anyMatch(rte -> !rte.routePoints.isEmpty());
     }
 
@@ -267,5 +267,5 @@
      * @return {@code true} if this GPX data is empty, {@code false} otherwise
      */
-    public boolean isEmpty() {
+    public synchronized boolean isEmpty() {
         return !hasRoutePoints() && !hasTrackPoints() && waypoints.isEmpty();
     }
@@ -301,7 +301,7 @@
      * @see #dataSources
      */
-    public Bounds recalculateBounds() {
+    public synchronized Bounds recalculateBounds() {
         Bounds bounds = null;
-        for (WayPoint wpt : getWaypoints()) {
+        for (WayPoint wpt : privateWaypoints) {
             if (bounds == null) {
                 bounds = new Bounds(wpt.getCoor());
@@ -310,5 +310,5 @@
             }
         }
-        for (GpxRoute rte : getRoutes()) {
+        for (GpxRoute rte : privateRoutes) {
             for (WayPoint wpt : rte.routePoints) {
                 if (bounds == null) {
@@ -319,5 +319,5 @@
             }
         }
-        for (GpxTrack trk : getTracks()) {
+        for (GpxTrack trk : privateTracks) {
             Bounds trkBounds = trk.getBounds();
             if (trkBounds != null) {
@@ -336,6 +336,6 @@
      * @return the length in meters
      */
-    public double length() {
-        return getTracks().stream().mapToDouble(GpxTrack::length).sum();
+    public synchronized double length() {
+        return privateTracks.stream().mapToDouble(GpxTrack::length).sum();
     }
 
@@ -362,5 +362,5 @@
      * @return minimum and maximum dates in array of 2 elements
     */
-    public Date[] getMinMaxTimeForAllTracks() {
+    public synchronized Date[] getMinMaxTimeForAllTracks() {
         double now = System.currentTimeMillis() / 1000.0;
         final DoubleSummaryStatistics statistics = tracks.stream()
@@ -384,5 +384,5 @@
      * end of a segment, or may be null if nothing close enough
      */
-    public WayPoint nearestPointOnTrack(EastNorth p, double tolerance) {
+    public synchronized WayPoint nearestPointOnTrack(EastNorth p, double tolerance) {
         /*
          * assume the coordinates of P are xp,yp, and those of a section of track between two
@@ -414,5 +414,5 @@
         double py = p.north();
         double rx = 0.0, ry = 0.0, sx, sy, x, y;
-        for (GpxTrack track : getTracks()) {
+        for (GpxTrack track : privateTracks) {
             for (GpxTrackSegment seg : track.getSegments()) {
                 WayPoint r = null;
@@ -502,6 +502,6 @@
      * Resets the internal caches of east/north coordinates.
      */
-    public void resetEastNorthCache() {
-        getWaypoints().forEach(WayPoint::invalidateEastNorthCache);
+    public synchronized void resetEastNorthCache() {
+        privateWaypoints.forEach(WayPoint::invalidateEastNorthCache);
         getTrackPoints().forEach(WayPoint::invalidateEastNorthCache);
         for (GpxRoute route: getRoutes()) {
@@ -594,5 +594,5 @@
 
     @Override
-    public int hashCode() {
+    public synchronized int hashCode() {
         final int prime = 31;
         int result = 1;
@@ -605,5 +605,5 @@
 
     @Override
-    public boolean equals(Object obj) {
+    public synchronized boolean equals(Object obj) {
         if (this == obj)
             return true;
