我有一个Singleton类处理一种带有Hashmap中不同对象的缓存。 (键的格式直接链接到存储在地图中的对象类型 - 因此地图是)
地图上可以执行三种不同的操作:添加,获取,删除。
我使用公共入口点方法(无强烈访问权限)保护了对地图的访问权限:
public synchronized Object doAction(String actionType, String key, Object data){
Object myObj = null;
if (actionType.equalsIgnorecase("ADD"){
addDataToMyMap(key,data);
} else if (actionType.equalsIgnorecase("GET"){
myObj = getDataFromMyMap(key);
} else if (actionType.equalsIgnorecase("REM"){
removeDataFromMyMap(key);
}
return myObj;
}
注意:
地图是私有的。方法addDataToMyMap(),getDataFromMyMap()和removeDataFromMyMap()都是私有的。只有入口点方法是公共的,除了类本身的静态getInstance()之外别无其他。
您是否确认并发访问地图是线程安全的,因为除了通过该方法之外没有其他方法可以使用地图?
如果它是Map的安全,我想这个原则可以应用于任何其他类型的共享资源。
非常感谢您的回答。
大卫
答案 0 :(得分:1)
我需要看看你的方法的实现,但它可能就足够了。 但我建议你使用java的Collection API中的Map,然后除非你共享其他实例,否则你不需要同步你的方法。
请阅读:http://www.java-examples.com/get-synchronized-map-java-hashmap-example
答案 1 :(得分:1)
是的,只要唯一的入口点是doAction,您的类就是线程安全的。
答案 2 :(得分:1)
如果您的cache
班级设有私人HashMap
且您有三种方法,且所有方法均为public synchronized
而非static
且您没有其他public
然后我认为你的缓存是thread-safe
。
最好发布您的代码。
答案 3 :(得分:1)
这是完全安全的。只要所有线程都使用公共锁访问它,在这种情况下是对象,那么它是线程安全的。 (其他答案可能更有效,但您的实施是安全的。)
答案 4 :(得分:0)
您可以使用Collections.synchronizedMap来同步对Map
的访问权限。
答案 5 :(得分:0)
因为很难确定代码是否是线程安全的。您的示例中缺少的重要信息包括:
我建议你研究synchronization以掌握问题以及如何解决这些问题。探索ConcurrentHashMap课程可以提供有关您的问题的更多信息。
答案 6 :(得分:0)
您应该使用ConcurrentHashMap。与Collections.synchronizedMap()相比,它提供了比同步doAction更好的吞吐量和更好的线程安全性。
答案 7 :(得分:0)
这取决于您的代码。正如其他人所说,您可以使用Collections.synchronizedMap。但是,这只会同步地图上的各个方法调用。所以如果:
map.get(key);
map.put(key,value);
在两个不同的线程中同时执行,一个将阻塞,直到另一个退出。但是,如果您的关键部分大于对地图的单个调用:
SomeExpensiveObject value = map.get(key);
if (value == null) {
value = new SomeExpensiveObject();
map.put(key,value);
}
现在让我们假设密钥不存在。第一个线程执行,并返回null值。调度程序产生该线程,并运行线程2,线程2也返回空值。 它构造新对象并将其放入地图中。然后线程1恢复并执行相同的操作,因为它仍然具有空值。
这是您需要围绕关键部分的更大同步块的地方
SomeExpensiveObject value = null;
synchronized (map) {
value = map.get(key);
if (value == null) {
value = new SomeExpensiveObject();
map.put(key,value);
}
}