You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The concurrency problem that has been previously raised is caused by misuse of SynchronizedMap. As noted in SynchronizedMap's javadoc, a synchronized-block must be placed around things that iterate the map (c.f. https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedMap-java.util.Map-). The QNameCache.getQNames() method fails to do this resulting in the possibility of ConcurrentModificationExceptions if getQNames() is iterating in thread#1 while thread#2 is mutating the map.
The use of a ConcurrentHashMap (as proposed as an enhancement in #15) would address this, but is complicated by a desire to preserve the WeakReferences within the map. That is, a ConcurrentWeakHashMap would solve it, but that is a heavy lift.
Instead, I would propose we simply follow the recommendation of SynchronizedMap. Namely:
public List<QName> getQNames() {
List<QName> answer = new ArrayList<QName>();
synchronized(noNamespaceCache) {
answer.addAll(noNamespaceCache.values());
}
synchronized(namespaceCache) {
for (Map<String, QName> map : namespaceCache.values()) {
answer.addAll(map.values());
}
}
return answer;
}
This will eliminate the bug and make Dom4j thread-safe. Implementing #15 in the future would additionally make it performant.
The text was updated successfully, but these errors were encountered:
This is related to Issue #15
The concurrency problem that has been previously raised is caused by misuse of SynchronizedMap. As noted in SynchronizedMap's javadoc, a synchronized-block must be placed around things that iterate the map (c.f. https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedMap-java.util.Map-). The QNameCache.getQNames() method fails to do this resulting in the possibility of ConcurrentModificationExceptions if getQNames() is iterating in thread#1 while thread#2 is mutating the map.
The use of a ConcurrentHashMap (as proposed as an enhancement in #15) would address this, but is complicated by a desire to preserve the WeakReferences within the map. That is, a ConcurrentWeakHashMap would solve it, but that is a heavy lift.
Instead, I would propose we simply follow the recommendation of SynchronizedMap. Namely:
This will eliminate the bug and make Dom4j thread-safe. Implementing #15 in the future would additionally make it performant.
The text was updated successfully, but these errors were encountered: