Cannot protect copying of synchronizedObservableMap

Robert Lichtenberger r.lichtenberger at
Thu Oct 17 12:48:39 UTC 2019

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 =
        Thread t = new Thread(() -> {
            while (true) {
                m.put(rnd.nextInt(1000), rnd.nextInt());
        Map<Integer, Integer> c = null;
        for (int i = 0; i < 100000; i ++) {
            synchronized(m) {
                c = new HashMap<>(m);

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;

* Is this considered a bug / a possible enhancement? Should there at least
be a warning against this possible pitfall?
* Do we need synchronizedObservable-Stuff in FXCollections at all? This
seems one of the cases where JavaFX contains classes/functionality that are
part of the JDK itself.

I can file an issue, if there is consensus about the issue.

More information about the openjfx-dev mailing list