2011-04-13 89 views
3

我有一个singleton类,它有一个可以被多个线程同时访问的地图。有人可以检查下面的代码,并告诉我它的线程是否安全? (注:我不打算使用的ConcurrentHashMap和printMap方法被调用只有很少。)synchronizedMap线程的这种用法是否安全?

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); 

       } 
      } 

     } 
    } 

我的测试工作......但我怀疑如果这个代码是不够好,被称为“线安全'。

点了,我认为:

  1. 的readValue和putValue方法并不需要有一个“同步”块,因为我使用的是synchronizedMap

  2. printMap应该有同步块,因为javadoc表示我们应该在每次迭代之前同步Map实例。 http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collections.html#synchronizedMap%28java.util.Map%29

任何帮助表示赞赏。

+0

在这里是有点挑剔,但那个班真的是单身人士吗? – DaveH 2011-04-13 12:19:10

+0

是的,它的春天豆 – rk2010 2011-04-13 12:28:30

+0

行 - 只是检查... :) – DaveH 2011-04-13 12:32:52

回答

4

是的,没关系。关键是,当你迭代时,没有东西可以修改地图,因为cache.put无论如何都会最终同步到cache

个人我宁愿通过使用“正常”散列映射并同步来自所有三种方法的同一对象(不管是地图还是其他方法) - 但是你应该没问题。

(或者,您也可以使用ConcurrentHashMap开始。这是值得至少在看那个。)

+1

实际上,当我查看代码时,cache.put正在同步一个名为mutex的内部对象。不是本身。有什么想法吗? – rk2010 2011-04-13 12:23:09

+0

@ rk2010:看看构造函数:'mutex = this;' – 2011-04-13 12:23:55

+1

我真的很喜欢你的正常哈希映射想法......! – rk2010 2011-04-13 12:24:29

0

是的,它是线程安全的。对缓存的每次访问都是同步的(通过synchronizedMap获取和设置,并通过printMap的显式同步块)

0

是的,该类是线程安全的。

,即使是线程安全类需要 安全出版物真正做到安全使用

虽然说明(无安全出版物没有保证其他线程无法看到未初始化状态cache,即null)。

但在这种情况下,你可以通过你的类不可变的(final关键字保证nullcache其他线程无法看到)消除安全出版物需要:

private final Map<String,String> cache = Collections.synchronizedMap(new LinkedHashMap<String,String>());