主要问题:用Java执行安全发布数组,集合或映射的内容的最佳方法是什么?
这是我尝试过的,还有一些附带问题:
侧面问题#1
在线程1上,我正在写入HashMap
:
HashMap
我目前的理解是:
[Map<K, V> map = new HashMap<>();
map.put(key, value);
并不构成地图中存储的参考的安全发布。
通过检查Collections.unmodifiableMap()
的实现,结果:
Collections.unmodifiableMap()
是线程安全的。Map.of()
是线程安全的。Map.of()
及更高版本不是线程安全的。我错了吗?
侧面问题2
现在,我想安全地公开在读取之前写入的Map.of()
的内容。我目前的理解是使用Map.of(key, value)
会导致性能下降,因此我宁愿避免在这种情况下使用它。
我想出了这种选择:
Map.of(key, value)
正确吗?有更好的方法吗?
侧面问题3
在线程1上,我正在写一个易失性数组:
Map.of(key1, value1, key2, value2)
我目前的理解是,从另一个线程读取Map.of(key1, value1, key2, value2)
是不安全的。为了安全起见,必须使用HashMap
。
这里是HashMap
的摘录:
ConcurrentHashMap
如果ConcurrentHashMap
无法获得与class MapSafePublication<K, V> {
private final Map<K, V> map = new HashMap<>();
private final ThreadLocal<Map<K, V>> safeMap = ThreadLocal.withInitial(() -> {
synchronized (MapSafePublication.this) {
return new HashMap<>(map);
}
});
synchronized void write(K key, V value) {
map.put(key, value);
}
V read(K key) {
return safeMap.get().get(key);
}
}
所使用的锁相同的锁,如何安全地从数组中读取?
volatile Object[] array = new Object[size];
array[index] = value;
的结果也是如此,据我目前的理解,这并不构成安全发布存储在参数对象中或由参数对象返回的引用。我错了吗?
回答您的第一部分:
Collections.unmodifiableMap()并不构成地图中存储的引用的安全发布。
正确。
通过检查Map.of()的实现...
唯一要检查的地方是Javadoc。如果未描述任何线程安全保证,则没有可靠的保证。可以更改实现以使事情“线程安全”,或删除线程安全。