为什么Object成员变量在Java中不是最终的和易变的?

如果在类中我有一个ConcurrentHashMap实例,它将被多个线程修改和读取,我可能会这样定义:

public class My Class { private volatile ConcurrentHashMap myMap = new ConcurrentHashMap(); ... } 

final添加到myMap字段会导致错误,说我只能使用final或volatile。 为什么不能两者兼而有之?

volatile只与变量本身的修改有关,而与它所引用的对象无关。 拥有final volatile字段是没有意义的,因为无法修改最终字段。 只要声明该字段final ,它应该没问题。

这是因为Java内存模型(JMM)。

基本上,当你将对象字段声明为final你需要在object的构造函数中初始化它,然后final字段不会改变它的值。 并且JMM承诺在ctor完成后,任何线程都会看到final字段的相同(正确)值。 因此,您不需要使用显式同步,例如synchronizeLock以允许所有线程查看final字段的正确值。

当您将对象的字段声明为volatile ,字段的值可以更改,但仍然可以从任何线程读取每个值的最新值。

因此, finalvolatile实现相同的目的 – 对象的字段值的可见性,但是首先专门用于变量,可以仅分配给一次,而第二次用于可以多次更改的变量。

参考文献:

因为volatilefinal是Java中的两个极端

volatile表示变量绑定到更改

final意味着变量的值永远不会改变

volatile字段可以保证您更改时发生的情况。 (没有可能引用的对象)

无法更改final字段(可以更改字段引用的内容)

两者都没有意义。

volatile用于它们的值可能改变的变量,在某些情况下,否则不需要volatilefinal意味着变量可能不会改变,因此不需要volatile

您的并发问题很重要,但是使HashMap volatile不能解决问题,因为处理并发问题,您已经使用了ConcurrentHashMap

因为它没有任何意义。 易失性影响对象引用值,而不是对象的字段/等。

在您的情况下(您有并发地图),您应该进行final的字段。

volatile修饰符保证所有读写操作都会进入主内存,即变量访问几乎进入synchronized块。 这与无法更改的最终变量无关。