我有一个单例类,它有一个可以由多个线程同时访问的映射。有人可以检查下面的代码并告诉我它的线程是否安全? (注意:我不打算使用ConcurrentHashMap,而且很少调用printMap方法。)
public class MySingleton{
private Map<String,String> cache = Collections.synchronizedMap(
new LinkedHashMap<String,String>());
public String getValue(String key){
return cache.get(key)
}
public void setValue(String key, String value){
cache.put(key, value);
}
public void printMap(){
synchronized(cache){
for(Entry<String,String> entry: cache.entrySet()){
println('key: '+entry.getKey()+', value: ' + value);
}
}
}
}
我的测试正在运行......但我怀疑这段代码是否足以被称为“线程安全”。
我考虑的要点:
readValue和putValue方法不需要有'synchronized'块,因为我使用的是synchronizedMap
printMap应该有synchronized块,因为javadoc表示我们应该在每次迭代之前同步Map实例。 http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29
感谢任何帮助。
答案 0 :(得分:4)
是的,没关系。关键是你在迭代时,没有任何东西可以修改地图,因为cache.put
最终会在cache
上同步。
个人我宁愿通过使用“普通”散列图并同步来自所有三种方法的同一对象(无论是地图还是其他东西)来明确这一点 - 但你要做什么得到的应该没事。
(或者,您可以使用ConcurrentHashMap
开始。至少值得考虑一下。)
答案 1 :(得分:0)
是的,它是线程安全的。每次访问缓存都是同步的(通过synchronizedMap进行get和set以及printMap的显式同步块)
答案 2 :(得分:0)
是的,这个类是线程安全的。
虽然注意即使是线程安全的类也要求安全发布才能真正安全地使用(没有安全发布,没有什么能保证其他线程在非初始化状态下看不到cache
,即null
)。
但在这种情况下,您可以通过使您的类不可变来消除安全发布的需要(final
关键字保证其他线程无法在null
中看到cache
):
private final Map<String,String> cache = Collections.synchronizedMap( new LinkedHashMap<String,String>());