我需要使以下类成为线程安全的:
//Shared among all threads
public class SharedCache {
private Map<Object, Future<Collection<Integer>>> chachedFutures;
{
chachedFutures = new ConcurrentHashMap<>(); //not sure about that
}
public Future<Collection<Integer>> ensureFuture(Object value,
FutureFactory<Collection<Integer>> ff){
if(chachedFutures.containsKey(value))
return chachedFutures.get(value);
Future<Collection<Integer>> ftr = ff.create();
chachedFutures.put(value, ftr);
return ftr;
}
public Future<Collection<Integer>> remove(Object value){
return chachedFutures.remove(value);
}
}
在阅读关于article课程的ConcurrentHashMap之后,我仍然难以做出正确的决定。
首先,我倾向于将方法ensureFuture
和remove
设为synchronized
。它会起作用,但从性能的角度来看,由于相互排斥,它并不是很好。
我不知道同时访问Cache
的确切(甚至大约)线程数量以及缓存的大小。考虑到
调整此大小或任何其他类型的哈希表是相对较慢的 操作
我没有指定地图的初始大小。还有concurrencyLevel参数。在这里使用ConcurrentHashMap
或同步方法是否足够?
答案 0 :(得分:2)
您有以下方法:
public Future<Collection<Integer>> ensureFuture(Object value,
FutureFactory<Collection<Integer>> ff){
if(chachedFutures.containsKey(value))
return chachedFutures.get(value);
Future<Collection<Integer>> ftr = ff.create();
chachedFutures.put(value, ftr);
return ftr;
}
public Future<Collection<Integer>> remove(Object value){
return chachedFutures.remove(value);
}
有一些要注意的地方:
ensureFuture
未同步,在这种情况下,一个线程可能会调用返回containsKey
的{{1}},但在执行下一行之前,另一个线程可能会删除相应的条目键。这可能会导致竞争状况,因为它是true
情景。也请检查this。check-then-act
,但IMO应使用chachedFutures.put(value, ftr)
。对于此方法chachedFutures.putIfAbsent(value, ftr)
。使用此功能,您还可以避免包含检查。在此使用ConcurrentHashMap或同步方法是否合理 会不够的?
由于CHM需要更多内存,因此需要更多内存,因为大量的簿记活动等。另一种方法是使用if the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value
来提供常规Collections.synchronizedMap
的同步。