synchronizedMap 的这种用法线程安全吗?
我有一个单例类,它有一个可以由多个线程同时访问的映射。有人可以检查下面的代码并告诉我它是否线程安全吗? (注意:我不打算使用 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 方法不需要有“同步”块,因为我使用的是 synchronizedMap
printMap 应该有synchronized 块,因为javadoc 说我们应该在每次迭代之前同步Map 实例。 http ://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29
感谢任何帮助。
I have a singleton class, that has a map which can be accessed by multiple threads at the same time. Could somebody please check the code below and tell me if its thread safe?
(note: I dont plan to use ConcurrentHashMap, and the printMap method is called only seldom.)
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);
}
}
}
}
My test is working... but i am doubting if this code is good enough to be called 'thread safe'.
points that I considered:
The readValue and putValue methods don't need to have a 'synchronized' block since i am using a synchronizedMap
printMap should have the synchronized block, since the javadoc for says that we should synchronize the Map instance before each iteration.
http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29
Any help is appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,没关系。关键是,当您进行迭代时,任何内容都无法修改映射,因为无论如何
cache.put
最终都会在cache
上同步。个人我宁愿通过使用“正常”哈希图并从所有三种方法同步同一对象(无论是地图还是其他东西)来明确这一点 - 但你所得到的应该是美好的。
(或者,您可以使用 ConcurrentHashMap 开始。至少值得一看。)
Yes, that's okay. The key thing is that while you're iterating, nothing will be able to modify the map because
cache.put
will end up synchronizing oncache
anyway.Personally I'd rather make that explicit, by using a "normal" hashmap and synchronizing on the same object (whether the map or something else) from all three methods - but what you've got should be fine.
(Alternatively, you could use
ConcurrentHashMap
to start with. It's worth at least looking at that.)是的,它是线程安全的。对缓存的每次访问都是同步的(通过 get 和 set 的同步映射以及 printMap 的显式同步块)
Yes it is thread safe. Each access to the cache is synchronized (by the synchronizedMap for get and set and by an explicit sync block for the printMap)
是的,这个类是线程安全的。
但请注意,即使是线程安全类也需要安全发布才能真正安全地使用(如果没有安全发布,则无法保证其他线程无法看到处于非初始化状态的缓存,即
null
)。但在这种情况下,您可以通过使类不可变来消除安全发布的需要(
final
关键字保证其他线程无法在cache
中看到null
代码>):Yes, this class is thread-safe.
Though note that even a thread-safe class requires safe publication to be used really safely (without safe publication nothing guarantees that other threads can't see
cache
in non-initialized state, i.e.null
).But in this case you can eliminate a need in safe publication by making your class immutable (
final
keyword guarantees that other threads can't seenull
incache
):