Cannot protect copying of synchronizedObservableMap
Robert Lichtenberger
r.lichtenberger at gmail.com
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 =
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;
}
Questions:
* 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