并发散列映射中值的原子更新-如何?

任务是跟踪一些正在运行的进程。将该信息保存在内存中很好,因此我使用并发散列映射来存储该数据:

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


解决方案

只要您只访问传递给compute的函数内的值,在该函数中所做的修改就是安全的。

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

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

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

相关文章