为什么Object成员变量在Java中不能是final和volatile?

时间:2012-02-17 12:32:50

标签: java multithreading syntax

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

public class My Class {

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

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

7 个答案:

答案 0 :(得分:28)

volatile仅与变量本身的修改有关,而与其引用的对象无关。拥有final volatile字段是没有意义的,因为无法修改最终字段。只需声明字段final,就可以了。

答案 1 :(得分:25)

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

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

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

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

  

参考文献:

     

答案 2 :(得分:7)

因为volatilefinal是Java中的两个极端

volatile表示变量绑定到更改

final表示变量的值永远不会改变

答案 3 :(得分:4)

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

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

两者都没有意义。

答案 4 :(得分:2)

volatile用于其值可能更改的变量,在某些情况下,否则不需要volatile,而final表示变量可能不会更改,因此有不需要volatile

您的并发问题很重要,但使HashMap volatile 无法解决问题,因为处理并发问题,您已使用ConcurrentHashMap

答案 5 :(得分:1)

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

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

答案 6 :(得分:1)

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