Skip to content

Commit 583e81d

Browse files
committed
#1412 fix concurrency issue in CopyOnWriteMap
the default method `Map.getOrDefault` is not thread-safe: the condition `if (v == null && containsKey(key))` leaves `v = null` if the `key` was added by another thread exactly at the same moment. Then both conditions are true: `v==null` and `containsKey(key)`. Now `CopyOnWriteMap.getOrDefault` does NOT check `containsKey(key)`. As a consequence, `CopyOnWriteMap` doesn't allow putting `null` values to the map.
1 parent 1dc01bb commit 583e81d

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

src/main/java/net/datafaker/internal/helper/CopyOnWriteMap.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import java.util.Set;
66
import java.util.function.Supplier;
77

8+
import static java.util.Objects.requireNonNull;
9+
import static java.util.Objects.requireNonNullElse;
10+
811
/**
912
* This is a Copy On Write map. The main idea behind this is that
1013
* there is lots of static info per provider to make the providers operate.
@@ -59,6 +62,7 @@ public V putIfAbsent(K key, V value) {
5962

6063
@Override
6164
public V put(K key, V value) {
65+
requireNonNull(value, () -> "value is null for key " + key);
6266
Map<K, V> newMap = mapSupplier.get();
6367
newMap.putAll(map);
6468
final V result = newMap.put(key, value);
@@ -102,4 +106,15 @@ public Collection<V> values() {
102106
public Set<Entry<K, V>> entrySet() {
103107
return map.entrySet();
104108
}
109+
110+
@Override
111+
public String toString() {
112+
return map.toString();
113+
}
114+
115+
@Override
116+
public V getOrDefault(Object key, V defaultValue) {
117+
V v = get(key);
118+
return requireNonNullElse(v, defaultValue);
119+
}
105120
}

0 commit comments

Comments
 (0)