为什么 Object 成员变量在 Java 中不能既是最终变量又是易失性的?

2022-08-31 21:30:23

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

public class My Class {

    private volatile ConcurrentHashMap<String,String> myMap = new ConcurrentHashMap<String,String>();
...
}

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


答案 1

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


答案 2

这是因为Java Memory Model(JMM)。

从本质上讲,当您声明对象字段时,您需要在对象的构造函数中初始化它,然后字段不会更改它的值。JMM承诺,在ctor完成后,任何线程都将看到相同(正确)的字段值。因此,您不需要使用显式同步,例如 或 允许所有线程查看正确的字段值。finalfinalfinalsynchronizeLockfinal

当您将对象的字段声明为 时,字段的值可以更改,但从任何线程读取值的每次操作都会看到写入它的最新值。volatile

所以,并达到相同的目的——对象的字段值的可见性,但首先专门用于一个变量只能被赋值一次,第二个用于一个可以更改多次的变量。finalvolatile

引用: