java - Java中的ConcurrentHashMap原子写入后能否实现对可变数据的读取?

标签 java concurrenthashmap

我试图找到这些问题的答案,但无法在 Google 或 Java 文档中理解(或确认)它。

我的实现是这样的:

Map<String, POJO> map = new ConcurrentHashMap<String, POJO>();

如果我这样做

value1 = map.get(key1);
value1.setProp(prop);

任何其他线程都可以覆盖。

现在,我在想如果我喜欢以下内容:它会是一个原子操作/换句话说,它会阻塞 key1 段吗?

map.compute(key1, (key1, value1) -> { value1.setProp(prop) });

compute 函数的 Javadoc

Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping). The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this Map.

引用资料:

1. https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html 2. https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction-

编辑:

对于我的最终实现,我做了类似这样的事情,因为所有线程共享 NewMap,最后,我创建了新的 POJO 列表
抽象数据类型

    public class NewMap {

        private Map<String, POJO> map;
        private boolean isUpdatable;
        void NewMap(){
              isUpdatable = true;
              map = new ConcurrentHashMap();
        }

        void putPOJOProp1(String key, Type value) throws ReadOnlyException{

                  map.compute(key, (k,v) -> {
                           if(!isUpdatable) throw new ReadOnlyException();
                           if(k == null){ 
                              POJO p = new POJO();
                              p.setProp1(value);
                              v = p;
                           } else { 
                              v = v.setProp1(v)
                           }
             });
        }

        void putPOJOProp2....
        void putPOJOProp3....

        List<POJO> getAll() {
             isUpdatable = false;
             List<POJO> pojos;
             for(key: map.getKeys()) {
                  Pojo p = map.get(key);
                  p.setKey(key);
                  pojos.add(p);
             }
             return pojos;
        }
    }

最佳答案

你混淆了两个不同的术语。
ConcurrentHashMap 防止内部结构损坏,但不能防止竞争条件。如果您只想避免数据损坏,那么使用 ConcurrentHashMap 是有效的。
但从你的问题来看,你似乎在试图避免竞争条件。 ConcurrentHashMap 不会以任何方式保护您免受它们的侵害。

为了更好地理解它,让我们看下面的例子:

    Map<String, POJO> map = new ConcurrentHashMap<>();
    ExecutorService pool = Executors.newWorkStealingPool(10);

    for (int t = 0; t < 10; t++) {
        pool.execute(() -> {
            for (int i = 0; i < 100_000; i++) {
                map.compute("A", (k, v) -> {
                    if (v == null) {
                        return new POJO();
                    }
                    v.a = ++v.a;
                    v.b = ++v.b;

                    return v;
                });
            }
        });
    }

    pool.awaitTermination(5, TimeUnit.SECONDS);

    System.out.println(map);

    // With POJO like 
    class POJO {
       // toString() here
       Integer a = 1;
       Integer b = 1;
    }

这里我们得到 {A=POJO{a=1000000, b=1000000}},所以我们的操作是线程安全的。如果这就是您想要的,那很好。

关于java - Java中的ConcurrentHashMap原子写入后能否实现对可变数据的读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51569111/

相关文章:

java - 恢复后无法重新部署 GCP App Engine 项目

java - 从 pom.xml 中查找所有可用的依赖项更高版本

java - 为什么从 ConcurrentHashMap 中删除第一个条目不会立即反射(reflect)在迭代器中,但删除第二个或后续条目会立即反射(reflect)在迭代器中?

java - 这段代码告诉计算机做什么 Lights[k] = !lights[k];?

带有注解的 Java 面向方面编程

java - 将类转换为java中的接口(interface)

Java 8 ConcurrentHashMap 每键 wait() 内的compute()

java - java并发hashmap中clear的默认行为是什么

java - 实现不同步读取的双缓冲java HashMap