synchronizedMap 的这种用法线程安全吗?

发布于 2024-11-01 04:38:30 字数 1212 浏览 1 评论 0原文

我有一个单例类,它有一个可以由多个线程同时访问的映射。有人可以检查下面的代码并告诉我它是否线程安全吗? (注意:我不打算使用 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 说我们应该在每次迭代之前同步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:

  1. The readValue and putValue methods don't need to have a 'synchronized' block since i am using a synchronizedMap

  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

冬天的雪花 2024-11-08 04:38:30

是的,没关系。关键是,当您进行迭代时,任何内容都无法修改映射,因为无论如何 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 on cache 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.)

紫南 2024-11-08 04:38:30

是的,它是线程安全的。对缓存的每次访问都是同步的(通过 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)

哥,最终变帅啦 2024-11-08 04:38:30

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

但请注意,即使是线程安全类也需要安全发布才能真正安全地使用(如果没有安全发布,则无法保证其他线程无法看到处于非初始化状态的缓存,即null)。

但在这种情况下,您可以通过使类不可变来消除安全发布的需要(final 关键字保证其他线程无法在 cache 中看到 null代码>):

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

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 see null in cache):

private final Map<String,String>  cache = Collections.synchronizedMap( new LinkedHashMap<String,String>()); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文