Java 'final' 实例变量 - 变量内部状态的可见性和传播
Java 'final' instance variable - visibility and propagation of variable's internal state
在看Threads and Locks相关的documentation时,一句话描述final
关键字吸引了我:
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.
这是否意味着,如果我将 final Object object = ...
声明为实例变量,然后从匿名内部 类(多个实例)访问它(修改其内部状态 - object.state
) Runnable
), 那么 object.state
的值实际上可能是 read/written from/into CPU 缓存并且它 (object.state
的值) 可能是 out在这些 Runnable
个实例之间同步?
因此,如果我想确定 object.state
的值在所有线程中正确传播,我必须将 object
声明为 volatile Object object
吗?
谢谢。
编辑:我已经编辑了我原来的问题。现在我知道我误解了文档,所以我最后一个问题的答案是 NO - volatile/final Object object
对 object.state
没有影响 - 这取决于 object.state
已声明,已初始化 and/or 已访问。
感谢@Burak Serdar 的回答!
当你声明一个final Object object=...
时,最终值是对对象的引用,而不是对象的内部状态。不是说什么都不能修改object
,不是说什么都不能修改,比如说object.value
。所以变量object
可以缓存,不代表object
的内部状态可以缓存
Final 无法按照您希望的方式帮助您解决线程问题,抱歉。
Volatile 在某些情况下可能会有所帮助,但您可能需要锁定。
来自 Oracle 教程:
-对于引用变量和大多数原始变量(除 long 和 double 之外的所有类型),读取和写入是原子的。
- 对于所有声明为 volatile 的变量(包括 long 和 double 变量),读写都是原子的。
这意味着您的对象不会在读取和写入之间立即更新,但它会在一个 read/write.
内保持一致
在看Threads and Locks相关的documentation时,一句话描述final
关键字吸引了我:
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.
这是否意味着,如果我将 final Object object = ...
声明为实例变量,然后从匿名内部 类(多个实例)访问它(修改其内部状态 - object.state
) Runnable
), 那么 object.state
的值实际上可能是 read/written from/into CPU 缓存并且它 (object.state
的值) 可能是 out在这些 Runnable
个实例之间同步?
因此,如果我想确定 object.state
的值在所有线程中正确传播,我必须将 object
声明为 volatile Object object
吗?
谢谢。
编辑:我已经编辑了我原来的问题。现在我知道我误解了文档,所以我最后一个问题的答案是 NO - volatile/final Object object
对 object.state
没有影响 - 这取决于 object.state
已声明,已初始化 and/or 已访问。
感谢@Burak Serdar 的回答!
当你声明一个final Object object=...
时,最终值是对对象的引用,而不是对象的内部状态。不是说什么都不能修改object
,不是说什么都不能修改,比如说object.value
。所以变量object
可以缓存,不代表object
的内部状态可以缓存
Final 无法按照您希望的方式帮助您解决线程问题,抱歉。 Volatile 在某些情况下可能会有所帮助,但您可能需要锁定。
来自 Oracle 教程:
-对于引用变量和大多数原始变量(除 long 和 double 之外的所有类型),读取和写入是原子的。 - 对于所有声明为 volatile 的变量(包括 long 和 double 变量),读写都是原子的。
这意味着您的对象不会在读取和写入之间立即更新,但它会在一个 read/write.
内保持一致