3

我有一个单例类,它有一个可以由多个线程同时访问的映射。有人可以检查下面的代码并告诉我它的线程是否安全吗?(注意:我不打算使用 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 方法不需要“同步”块,因为我使用的是 synchronizedMap

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

任何帮助表示赞赏。

4

3 回答 3

4

是的,没关系。关键是当你在迭代时,什么都不能修改地图,因为无论如何cache.put都会同步。cache

就我个人而言,我宁愿通过使用“普通”哈希图并通过所有三种方法在同一个对象(无论是地图还是其他东西)上同步来明确这一点 - 但你所拥有的应该没问题。

(或者,您可以使用ConcurrentHashMap开始。至少值得一看。)

于 2011-04-13T12:16:14.823 回答
0

是的,这个类是线程安全的。

尽管请注意,即使是线程安全的类也需要真正安全地使用安全发布(没有安全发布,就不能保证其他线程cache在非初始化状态下看不到,即null)。

但是在这种情况下,您可以通过使您的类不可变来消除对安全发布的需求(final关键字保证其他线程看不到nullcache

private final Map<String,String>  cache = Collections.synchronizedMap( new LinkedHashMap<String,String>()); 
于 2011-04-13T12:19:02.267 回答
0

是的,它是线程安全的。对缓存的每次访问都是同步的(通过 synchronizedMap 进行 get 和 set 以及通过显式同步块进行 printMap)

于 2011-04-13T12:16:49.723 回答