简体   繁体   English

插入并发哈希映射

[英]inserting in a concurrent hash map

The following piece of code does not work as expected. 以下代码不能按预期工作。 When I call put method in Does class the value in the concurrent hash map is associated with different instances of map. 当我在Do类中调用put方法时,并发哈希映射中的值与不同的map实例相关联。 So what I am trying to do is multiple threads access the same map and insert a value for the same key. 所以我想要做的是多个线程访问相同的映射并为同一个键插入一个值。 However if I add a synchronized keyword to the put method it works. 但是,如果我将一个synchronized关键字添加到put方法,它就可以工作。 What am I missing? 我错过了什么?

class Does implements Runnable {
    C2 c2;

    Does(C2 c2) {
        this.c2 = c2;
    }

    public void run() {
        c2.put("Hello");
    }

}

public class C2 {
    public ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<String, List<String>>();

    public static void main(String args[]) {
        C2 c2 = new C2();
        new Thread(new Does(c2)).start();
        new Thread(new Does(c2)).start();
        new Thread(new Does(c2)).start();
        new Thread(new Does(c2)).start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        List<String> lu = c2.map.get("Hello");

        System.out.println(lu);
    }

    /**
     * @param string
     */
    public void put(String string) {
        if (map.containsKey(string)) {
            List<String> li = map.get(string);
            li.add("adding something");
        } else {
            List<String> li = new ArrayList<String>();
            li.add("adding something");
            map.put(string, li);
        }
    }

}

Appreciate the help. 感谢帮助。

This code is not thread safe 此代码不是线程安全的

public void put(String string) {
    if (map.containsKey(string)) {
        // anything can happen in another thread here
        List<String> li = map.get(string);
        // anything can happen in another thread here
        li.add("adding something");
    } else {
        // anything can happen in another thread here
        List<String> li = new ArrayList<String>();
        li.add("adding something");
        // anything can happen in another thread here
        map.put(string, li);
    }

In Java 8 you can use computeIfAbsent. 在Java 8中,您可以使用computeIfAbsent。

public void put(String string) {
    // all most thread safe.
    map.computeIfAbsent(string, k -> new ArrayList<>())
       .add("add something");
}

Note this is still not thread safe as the ArrayList is not thread safe, so what you need is 请注意,这仍然不是线程安全的,因为ArrayList不是线程安全的,所以你需要的是

public void put(String string) {
    List<String> list = map.computeIfAbsent(string, k -> new ArrayList<>());
    synchronized(list) {
       list.add("add something");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM