以下实现线程是否安全?

时间:2016-11-02 10:35:23

标签: java multithreading synchronization

我有一个java线程安全映射,它存储String到Object映射:

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的引用的唯一方法。这个实现线程安全吗?

1 个答案:

答案 0 :(得分:3)

  

以下实施线程是否安全?

如果您始终使用此MyObject实例访问和修改同步块中的MyObject的给定实例,则取决于您在代码中访问和修改MyObject实例的方式作为对象的监视器,然后它是线程安全的,否则它不会。

您的put方法不是线程安全的,因为putIfAbsent并且replace未执行原子,这可能会导致竞争条件问题,使用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;
        }
    );
}