提问者:小点点

并发哈希映射中值的原子更新-如何?


任务是跟踪一些正在运行的进程。将这些信息保存在内存中很好,所以我使用并发哈希映射来存储这些数据:

ConcurrentHashMap<String, ProcessMetaData> RUNNING_PROCESSES = new ConcurrentHashMap();

安全地将新对象放入映射中一切都很好,问题是这些进程的状态会发生变化,所以我必须不时更新ProcessMetaData。我使ProcessMetaData不可变,并使用ConCurrentHashMapcompute()方法来更新值,但现在的问题是ProcessMetaData变得更加复杂,并且保持它不可变很难管理。问题是-只要我只在原子(根据javadoc)compute()方法中更新ProcessMetaData-对象可能是可变的,总体上仍然是线程安全的?我的假设正确吗?


共1个答案

匿名用户

只要您只访问传递给compute的函数中的值,在该函数中进行的修改是安全的。

然而,这是一个毫无意义的理论观点。将值存储到集合或映射中的目的是最终检索和使用它们。这就是问题的开始。

compute方法返回结果值,就像get返回当前存储的值一样。一旦调用者开始使用该值,这种使用可能会与映射上的后续compute操作并发。get方法甚至可能在compute操作正在进行时检索该值。允许非阻塞检索操作是ConCurrentHashMap的主要功能之一。因此,各种竞争条件都可能发生。

因此,使用可变对象并修改compute中已经存储的值是唯一安全的,当您将map用作只写内存时,这是一个牵强的场景。当您使用不同的线程安全机制以确保在开始读取map之前已完成所有更新时,它可能会起作用,但您的用例似乎不同。