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

SynchronizedObservableMap cannot be be protected for copying/iterating

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • jfx14
    • jfx13, 8
    • javafx
    • None
    • generic
    • generic

      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;
               }

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

              Created:
              Updated:
              Resolved: