2016-11-02 89 views
1

我有一个Java线程安全的地图存储字符串对象映射:以下实现线程安全吗?

ConcurrentHashMap<String, MyObject> map = new ConcurrentHashMap<>(); 

这里MyObject的是用户定义的类。现在考虑下面的方法:

public void replace(String key, MyObject o) { 
    MyObject m = map.get("somekey"); 
    synchronized(m) { 
     // Modify some internal components of m 
     // and some other objects related to m 
    } 
} 

我的目的是在这里我想不把锁在全班但只能在线程试图访问地图相同的密钥,以最大限度地提高性能。基本上每次在地图中替换一个条目(不添加),这部分代码就会被执行。喜欢的东西:

public void put(String key, MyObject o) { 
    if (map.putIfAbsent(key, o) == null){ //do something 
    } 
    else { 
     replace(key, o); 
    } 
} 

从实际出发,我们可以认为这是通过为myObject一个参考是可以改变的唯一方法。这个实现线程安全吗?

+0

这是不可能知道没有'MyObject'的实现,并且if有可能以另一种方式访问​​这个特定的实例。但简单的答案是:可能不是。 –

+0

@MarkRotteveel我同意我的问题不完整。我现在添加了更多的细节。 – Sohaib

+0

我迷路'replace'和'put'都在你的代码中? –

回答

3

以下实现是否线程安全?

这取决于你如何访问和修改的MyObject情况下,在你的代码,如果你总是一个synchronized块内使用该MyObject实例作为对象的监视器则是这将是线程访问和修改的MyObject给定实例安全,否则不会。


put方法不是线程安全putIfAbsentreplace不执行原子这可能导致竞争条件问题,使用merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)到做同样的事情,但原子在明年:

public void put(String key, MyObject o) { 
    map.merge(
     key, o, 
     (v1, v2) -> { 
      // Modify some internal components of v1 
      // and some other objects related to v1 
      return v2; 
     } 
    ); 
} 
+0

是的,我的问题不是关于修改myObject,而是其他人可能试图通过用不同的MyObject实例替换它来操作映射的同一个键的事实。 – Sohaib

+0

检查我的响应更新关于put方法,是你想要的吗? –

+0

是的,但我需要更新一些入门。我认为这里的正确方法是这样的答案: http://stackoverflow.com/a/5640671/1901744 即使我认为它不是高性能的,这可能工作。 – Sohaib