【问题标题】:how to make access to a value in a Java Hashmap synchronized?如何同步访问 Java Hashmap 中的值?
【发布时间】:2020-02-29 18:28:16
【问题描述】:

假设我有一个 Java Hashmap,其中键是字符串或其他内容,值是其他值的列表,例如

Map<String,List<String>> myMap=new HashMap<String,List<String>>();
//adding value to it would look like this
myMap.put("catKey", new ArrayList<String>(){{add("catValue1");}} );

如果我们有许多线程在列表中添加和删除值(不更改键,只是更改 Hashmap 的值),是否有办法使对列表的访问仅是线程安全的?让多个线程可以同时编辑多个值?

【问题讨论】:

  • 是的,使用同步或并发列表实现而不是ArrayList

标签: java arraylist hashmap


【解决方案1】:

使用同步或并发列表实现而不是ArrayList,例如

最后一个不是列表,但如果您实际上不需要按索引访问(即随机访问),则它很有用,因为它的性能优于其他列表。


注意,由于您可能需要将初始空列表同时插入到映射中以获得新键,因此您应该为 Map 本身使用 ConcurrentHashMap,而不是普通的 HashMap


推荐

Map<String, Deque<String>> myMap = new ConcurrentHashMap<>();

// Add new key/value pair
String key = "catKey";
String value = "catValue1";
myMap.computeIfAbsent(key, k -> new ConcurrentLinkedDeque<>()).add(value);

上面的代码在向映射中添加新键时是完全线程安全的,在向列表中添加新值时是完全线程安全的。代码不会花时间获取同步锁,也不会遭受CopyOnWriteArrayList在列表变大时的降级。

唯一的问题是它使用Deque,而不是List,但实际上List 的大多数使用都可以很容易地使用Deque,但是指定了List out习惯,所以这可能是一个可以接受的改变。

【讨论】:

    【解决方案2】:

    有一个ConcurrentHashMap 类实现了ConcurrentMap,可用于线程安全的Map 处理。 computeputIfAbsentmerge,所有线程安全地处理多个试图同时影响相同值的事情。

    【讨论】:

    • 问题说“许多线程在列表中添加和删除值(不改变键只是Hashmap的值)”,所以多线程访问地图是不是主要问题,对列表的多线程访问是。 computemerge 是唯一的解决方案,如果您打算在每次修改时克隆列表,因为您可以使用 CopyOnWriteArrayList 并免费获得该逻辑。
    • @Andreas:我不反对。但几乎可以肯定会有多个线程检索来自Map 的值(并初始化它们等)。无论如何,此时您可能想要ConcurrentMap。我认为这里的 both 建议的组合实际上将解决 OP 所询问的问题。 (不过,同意你的回答要彻底得多。)
    【解决方案3】:

    首先使用将同步特定存储桶的并发哈希映射。

    其次必须使用原子函数,否则当一个线程使用get方法时,另一个线程可以调用put方法。如下所示

    // wrong 
    if(myMap.get("catKey") == null){
        myMap.put("catKey",new ArrayList<String>(){{add("catValue1");}});       
    }
    
    //correct
    myMap.compute("catKey", (key, value) -> if(value==null){return new ArrayList<String>(){{add("catValue1");}}} return value;);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 1970-01-01
      • 2019-04-27
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      相关资源
      最近更新 更多