synchronizedMap线程的这种用法是否安全?

时间:2011-04-13 12:12:51

标签: java synchronization thread-safety linkedhashmap

我有一个单例类,它有一个可以由多个线程同时访问的映射。有人可以检查下面的代码并告诉我它的线程是否安全? (注意:我不打算使用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);

               }
          }

      }
    }

我的测试正在运行......但我怀疑这段代码是否足以被称为“线程安全”。

我考虑的要点:

  1. readValue和putValue方法不需要有'synchronized'块,因为我使用的是synchronizedMap

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

  3. 感谢任何帮助。

3 个答案:

答案 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>());