考虑以下某种固定大小缓存的实现,它允许通过整数句柄进行查找:
static class HandleCache {
private final AtomicInteger counter = new AtomicInteger();
private final Map<Data, Integer> handles = new ConcurrentHashMap<>();
private final Data[] array = new Data[100_000];
int getHandle(Data data) {
return handles.computeIfAbsent(data, k -> {
int i = counter.getAndIncrement();
if (i >= array.length) {
throw new IllegalStateException("array overflow");
}
array[i] = data;
return i;
});
}
Data getData(int handle) {
return array[handle];
}
}
计算函数内部有一个数组存储,它不以任何方式同步。 Java 内存模型是否允许其他线程稍后从该数组读取空值?
PS:如果从 getHandle
返回的 id 存储在 final
字段中并且只能通过该字段从其他字段访问,结果会改变吗线程?
最佳答案
读取访问不是线程安全的。您可以间接使其线程安全,但它可能很脆弱。我会以更简单的方式实现它,并且只有在它被证明存在性能问题时才对其进行优化。例如因为您会在分析器中看到它以进行实际测试。
static class HandleCache {
private final Map<Data, Integer> handles = new HashMap<>();
private final List<Data> dataByIndex = new ArrayList<>();
synchronized int getHandle(Data data) {
Integer id = handles.get(data);
if (id == null) {
id = handles.size();
handles.put(data, id);
dataByIndex.add(id);
}
return id;
}
synchronized Data getData(int handle) {
return dataByIndex.get(handle);
}
}
关于java - ConcurrentHashMap.computeIfAbsent 中的赋值是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49945202/