Java中的’final’实例变量 – 变量的可见性和内部状态的传播

huangapple go评论77阅读模式
英文:

Java 'final' instance variable - visibility and propagation of variable's internal state

问题

在阅读与线程和锁有关的文档时,有一句描述final关键字的句子引起了我的注意:

> 相应地,编译器允许将final字段的值保留在寄存器中,而不是在需要重新加载非final字段的情况下从内存中重新加载它。

这是否意味着,如果我将final Object object = ...声明为实例变量,然后从匿名内部类(多个Runnable实例)中访问它(修改其内部状态 - object.state),那么object.state的值实际上可以从/写入到CPU缓存中,并且它(object.state的值)可能在这些Runnable实例之间不同步?

因此,如果我想确保object.state的值在所有线程之间正确传播,我必须将object声明为volatile Object object,是吗?

谢谢。


编辑:我已编辑了原始问题。现在我知道我误解了文档,所以对于我最后的问题,答案是不是 - volatile/final Object objectobject.state没有影响 - 它取决于如何声明、初始化和/或访问object.state

感谢@Burak Serdar的答复!

英文:

While reading the documentation related to Threads and Locks, a sentence describing final keyword attracted me:

> Correspondingly, compilers are allowed to keep the value of a final field cached in a register and not reload it from memory in situations where a non-final field would have to be reloaded.

Does it mean, that if I declare a final Object object = ... as an instance variable and then access it (modify its inner state - object.state) from anonymous inner classes (multiple instances of Runnable), then the value of object.state could actually be read/written from/into CPU cache and it (value of object.state) could be out of sync across those Runnable instances?

So if I want to be sure, that the value of object.state is properly propagated across all the threads I have to declare the object as volatile Object object instead?

Thank you.


Edit: I have edited my original question. And now I know I misunderstood the documentation so the answer to my last question is NO - volatile/final Object object has no effect on object.state - it depends how the object.state is declared, initialized and/or accessed.

Thanks to the @Burak Serdar for the answer!

答案1

得分: 3

当您声明 final Object object = ... 时,最终的值是指向该对象的引用,而不是对象的内部状态。这意味着任何内容都不能修改 object 本身,但这并不意味着不能修改例如 object.value 这样的内容。因此,变量 object 可能会被缓存,但这并不意味着可以缓存 object 的内部状态。

英文:

When you declare a final Object object=..., the final value is the reference to the object, not the internal state of the object. It means than nothing can modify object, it does not say that nothing can modify, say, object.value. So the variable object can be cached, which does not mean the internal state of object can be cached.

答案2

得分: -1

以下是翻译好的内容:

Final 不会像你希望的那样帮助你解决线程问题,抱歉。
在某些情况下,Volatile 可能会有所帮助,但你可能需要使用锁。

来自 Oracle 教程:

-对于引用变量和大多数原始变量(除了 long 和 double 类型),读取和写入是原子的。
-对于所有声明为 volatile 的变量(包括 long 和 double 变量),读取和写入都是原子的。

这意味着在读取和写入之间,你的对象不会立即更新,但在一个读取/写入内部是一致的。

英文:

Final will not help you with threading issues the way you hope, sorry.
Volatile may help in some situations, but you may need a lock.

From the Oracle tutorials:

-Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
-Reads and writes are atomic for all variables declared volatile (including long and double variables).

That means your object will not be immediately updated between reads and writes, but it will be consistent within one read/write.

huangapple
  • 本文由 发表于 2020年4月4日 06:40:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/61021473.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定