有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何处理对存储在映射中的POJO的并发更新和读取

我计划使用最多由2个并发线程操作的CHM实现一个用于查找的简单内存缓存。一个线程使用迭代器迭代和更新CHM,第二个线程从映射中读取值

根据我的理解,我到目前为止所经历的CHM迭代器是故障安全的,这意味着迭代将发生在数据的快照上

因此,假设线程A从CHM中提取一个值,该值是使用键的POJO,并且它正在迭代/更新POJO。同时,ThreadB在同一个POJO上运行。那么,此时的预期行为是什么呢

  • ThreadB会看到ThreadA正在进行的更新吗?我猜不是因为线程仍然在进行更新。<李>
  • 如果是的话,请分享你的想法,那会怎样
  • 如果没有,请建议有效的替代方法,如果你已经实施了

POJO有点像下面

Class Pojo{
    private volatile long a;
    private volatile long b;
    ....    

    public long getA() {
        return this.a;
    }

    void setA(long a) {
        this.a = a;
    }
}

共 (3) 个答案

  1. # 1 楼答案

    • CHM的值应该是原子参考
    • 使Pojo类不可变,更新任何新值都会创建一个新的Pojo对象
    • 实现一个接受构造函数中所有参数的构造函数
    • 实现下面给出的每个set方法
    public Pojo setA(int newA ){
        Pojo newPojo = new Pojo(newA, this.getB());
        return newPojo;
    }
    
    • 更新CHM时,请遵循以下步骤
    AtomicReference pojoRef = CHM.get(Key);
    Pojo oldPojo = pojoRef.get();
    Pojo newPojo = oldPojo.setA(10);
    while(!pojoRef.compareAndSet(oldPojo, newPojo) ){
        AtomicReference pojoRef = CHM.get(Key);
        Pojo oldPojo = pojoRef.get();
        Pojo newPojo = oldPojo.setA(10);
    }
    
  2. # 2 楼答案

    你不能这样做吗

    Pojo myPojo = new Pojo();
    myPojo.setA(10);
    myPojo.setB(11);
    
    // Atomic replace
    CHM.replace(key, myPojo);
    

    CHM replace是原子的,在进行替换时,其他线程不会读取POJO的过时值

  3. # 3 楼答案

    As my understanding goes and what I have experienced till now CHM Iterator is fail safe which would mean iteration would happen on a snapshot of data.

    这是不对的。每the documentation

    Similarly, Iterators, Spliterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration.

    [强调我的]


    So let's assume Thread A extracts a value from CHM which is a POJO using a key and it is iterating/updating the POJO. At the same time ThreadB does a get on the same POJO. So what would be the expected behavior at this point?

    如果线程A正在变异一个POJO,而线程B正在检查同一个POJO,那么ConcurrentHashMap一点也不相关:两个线程如何获得POJO并不重要,只有POJO本身如何处理并发更新和读取

    您还没有告诉我们关于POJO类的任何信息,但除非它经过精心设计,允许原子更新和读取,否则线程B有时会以不一致的状态查看POJO,线程a的一些读取,但不是全部读取