Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8232524

SynchronizedObservableMap cannot be be protected for copying/iterating

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 8, openjfx13
    • Fix Version/s: openjfx14
    • Component/s: javafx
    • Labels:
      None
    • Subcomponent:
    • CPU:
      generic
    • OS:
      generic

      Description

      I've just stumbled upon a devious detail in
      javafx.collections.FXCollections.SynchronizedObservableMap<K, V>. Although
      it almost looks like a twin of Collections.synchronizedMap it does not
      allow to protect copying or iterating over it the way
      Collections.synchronizedMap does.

      Example program:
      import java.util.Collections;
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Random;
      import javafx.collections.FXCollections;

      public class SyncMap {
           public static void main(String[] args) {
               Random rnd = new Random();
               Map<Integer, Integer> m = Collections.synchronizedMap(new
      HashMap<Integer, Integer>());
      // Map<Integer, Integer> m =
      FXCollections.synchronizedObservableMap(FXCollections.observableHashMap());
               Thread t = new Thread(() -> {
                   while (true) {
                       m.put(rnd.nextInt(1000), rnd.nextInt());
                   }
               });
               t.setDaemon(true);
               t.start();
               Map<Integer, Integer> c = null;
               for (int i = 0; i < 100000; i ++) {
                   synchronized(m) {
                       c = new HashMap<>(m);
                   }
               }
               System.out.println(c);
           }
      }

      Using Collections.synchronizedMap this works, because we synchronize on m.
      If using FXCollections.synchronizedObservableMap this throws
      ConcurrentModificationException. The reason is that
               SynchronizedObservableMap(ObservableMap<K, V> map) {
                   this(map, new Object());
               }
      SynchronizedObservableMap uses a new Object as mutex instead of itself as
      seen in
               SynchronizedMap(Map<K,V> m) {
                   this.m = Objects.requireNonNull(m);
                   mutex = this;
               }

        Attachments

          Activity

            People

            • Assignee:
              rlichten Robert Lichtenberger
              Reporter:
              rlichten Robert Lichtenberger
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: