Java ConcurrentHashMap非阻塞读取和内存可见性问题

Java ConcurrentHashMap非阻塞读取和内存可见性问题,java,concurrency,concurrenthashmap,Java,Concurrency,Concurrenthashmap,Java中的ConcurrentHashMap提供了读操作,以便与更新同时进行。在这方面的权衡是,读取的结果仅限于在读取开始时反映上次完成的更新,因此没有指定它来反映元素的最新状态 但是,在AIK Java内存模型中,如果读线程和写线程之间没有某种形式的同步,则读线程可能看不到写线程的更新,即使在任意时间段之后也是如此 如果读线程不使用写线程阻塞,那么什么构成了保证读线程可以看到上次完成的更新的基础 我只能在正在使用的比较和交换算法中想到一些东西,但我无法在该实验室的源代码中验证它。读取的值实际

Java中的
ConcurrentHashMap
提供了读操作,以便与更新同时进行。在这方面的权衡是,读取的结果仅限于在读取开始时反映上次完成的更新,因此没有指定它来反映元素的最新状态

但是,在AIK Java内存模型中,如果读线程和写线程之间没有某种形式的同步,则读线程可能看不到写线程的更新,即使在任意时间段之后也是如此

如果读线程不使用写线程阻塞,那么什么构成了保证读线程可以看到上次完成的更新的基础


我只能在正在使用的比较和交换算法中想到一些东西,但我无法在该实验室的源代码中验证它。

读取的值实际上是可变负载。虽然它是非阻塞的,但您将确保“先发生后发生”关系,因为存储也是不稳定的


Java5,6,7版本的CHM不使用CAS交换引用。但是现在有一个更新的轻量级版本将用于它的一些写作。

是的,我现在看到
类HashEntry
有一个
volatile
值。早些时候,我只是检查了
HashEntry[]表
引用。虽然这是一个好问题,但当我第一次了解到CHM是一种部分非阻塞算法时,我觉得很奇怪。CHM在读取时是(始终是)非阻塞的。Put是通过锁省略来实现的,锁省略或多或少是正常的,但它的伸缩性不太好。不过,CAS确实存在以获取锁。这是一个既不阻塞写入也不阻塞读取的版本。是的,CAS是在tryAcquire上完成的。我更多的是暗示CHM本身没有明确使用CAS,类似于Java 8的CHMv8发行候选版本。每次写入(put)都是通过锁获取(加上易失性写入)进行的,以确保“可见性”。每次读取(get)都会执行一次易失性读取,以确保读卡器的可见性。