Java ConcurrentHashMap中的线程安全get方法

Java ConcurrentHashMap中的线程安全get方法,java,multithreading,concurrenthashmap,Java,Multithreading,Concurrenthashmap,我知道并发HashMap一次只允许一个线程为“每个段”更新/写入操作。但是,允许多个线程同时从映射中读取值 对于我的项目,我希望扩展此功能,以便在从特定段获取值时,在读取完成之前,不应在该段中执行更新/写入操作 有什么想法可以实现这一点吗?扩展ConcurrentHashMap类,并通过包含synchronized块来实现getValue()方法,以便在读取操作完成之前不允许访问其他线程 我只是想详细说明一下我现在面临的问题。从映射中读取值后,我执行某些更新操作,这些操作强烈依赖于该读取值。因此

我知道并发HashMap一次只允许一个线程为“每个段”更新/写入操作。但是,允许多个线程同时从映射中读取值
对于我的项目,我希望扩展此功能,以便在从特定段获取值时,在读取完成之前,不应在该段中执行更新/写入操作


有什么想法可以实现这一点吗?

扩展ConcurrentHashMap类,并通过包含synchronized块来实现getValue()方法,以便在读取操作完成之前不允许访问其他线程

我只是想详细说明一下我现在面临的问题。从映射中读取值后,我执行某些更新操作,这些操作强烈依赖于该读取值。因此,如果一个单独的线程更新键值,而另一个线程get()无法获取最近更新的值,这将导致一个大混乱。那么在这种情况下,扩展将是一个好主意

我的直觉是否定的。扩展
ConcurrentHashMap
听起来不是个好主意

您可以遵循的最有价值的设计原则之一是“关注点分离”。HashMap的主要“关注点”是存储键/值对。听起来,在程序中的某些数据之间保持一致的关系是另一个问题


不要试图用一个类来解决这两个问题。我会创建一个更高级别的类来维护一致的关系(可能通过使用
Lock
对象),我会使用一个普通的
HashMap
ConcurrentHashMap
来存储键/值对。

非正式地说,你可以把一个映射看作是一组“变量”,每个“变量”由键寻址(而不是普通变量的静态名称)

(数组形式上是一个变量列表,每个变量由一个整数索引寻址。)

在HashMap中,这些“变量”类似于“普通”变量;如果同时访问“变量”,则可能会出错(就像普通的非易失性变量一样)

在ConcurrentHashMap中,这些“变量”具有
volatile
语义。因此,同时使用“更”安全。例如,“后续”读取可以看到写入

当然,
volatile
有时是不够的;例如,我们知道不能对原子增量使用volatile int(没有锁定)。我们需要像AtomicInteger这样的新设备来进行原子操作


幸运的是,在Java8中,新的原子方法被添加到ConcurrentHashMap中,因此现在我们可以对这些“变量”进行原子操作。查看
compute()
方法是否适合您的用例。

使用您想要的功能实现。谢谢您的建议。我只是想详细说明一下我现在面临的问题。从映射中读取值后,我执行某些更新操作,这些操作强烈依赖于该读取值。因此,如果一个单独的线程更新键值,而另一个线程get()无法获取最近更新的值,这将导致一个大混乱。所以在这种情况下,扩展将是一个好主意?谢谢!计算机似乎是一个很好的选择。根据文档“其他线程在此映射上尝试的某些更新操作可能会在计算过程中被阻止,因此计算应该简短,并且不得尝试更新此映射的任何其他映射。”唯一需要考虑的是“可能被阻止”部分的非阻塞并发性,我们通常可以使用CAS——“比较和交换”。我们读取当前值(v0),进行一些(长时间)计算以获得v1,然后仅当该值仍然为v0时,我们尝试将该值设置为v1,即同时不进行更改。我们可以对CAS使用
compute()
。如果尝试失败,即当时的值不再是v0,我们将再次循环,读取当前值,进行计算,尝试CAS,等等。这种方法的缺点是它可能成为一个无限循环:)看看CAS如何实现原子加法。