当前位置:  开发笔记 > 编程语言 > 正文

是否必须在多线程环境中为long类型实例常量声明volatile?

如何解决《是否必须在多线程环境中为long类型实例常量声明volatile?》经验,为你挑选了1个好方法。

我有一个多线程Java程序,其中很少有长类型的常量,这些常量在多个线程调用的函数中被读取.这些读取/赋值操作在synchronized块外部,并且这些常量在与调用/ synchronizedblock的函数相同的类中声明.

这些长常数是否可取volatile?初始化后,这些常量不会被更改.我没有看到任何不正确的程序行为,只是想澄清一下.

这是伪代码,

public class ThreadSafeClass {
private long long_val = 100;

public int calculate(){

long local_long=long_val;

synchronized(this){
  //use local_long
}}}

Stephen C.. 5

如果long常量声明为final并且它们安全地发布为1,那么它们不需要声明为volatile.final字段的特殊属性在JLS 17.5中指定.

如果long常量不是final,则需要进行更深入的分析以确定它们是否真的是常量,以及初始化的结果是否对所有线程都可见.

声明(非final)常量volatile会实现这一点,但这不是一种好的(有效的)方法.深入分析(即仔细分析之前发生的关系)可能会发现这volatile是不必要的.例如,如果一个线程初始化了常量,然后THEN调用start()了所有使用它们的其他线程,那么(我认为)你可以逃避volatile没有其他同步.

但是......宣布常数final是更强大的方法2.


更新更新后的问题中的伪代码:

    伪代码版本是不正确的,即使它在其他任何地方都没有改变.问题是是否所有线程都能保证看到初始值.问题是内存模型不需要long_val由创建ThreadSafeClass实例的线程刷新.这意味着另一个线程在调用时可以看到默认的初始值(零)calculate().

    如果local_long被初始化synchronized块,伪代码将是正确的.

    如果long_valfinalvolatile, then the同步`块将不需要(至少为此目的).(出于不同的原因......)


1 - 基本上,您需要确保在"最终"生效之前没有其他线程使用常量字段.对于最终实例字段,这意味着在构造函数返回之前.对于最终的静态字段,这意味着在类初始化完成之前......当然注意到作为编译时常量的静态最终字段的处理方式不同.

2 - 我排除了使用反射来改变final字段的边缘情况.这是邪恶的,它使所有关于可见性的保证无效.只是不要这样做.



1> Stephen C..:

如果long常量声明为final并且它们安全地发布为1,那么它们不需要声明为volatile.final字段的特殊属性在JLS 17.5中指定.

如果long常量不是final,则需要进行更深入的分析以确定它们是否真的是常量,以及初始化的结果是否对所有线程都可见.

声明(非final)常量volatile会实现这一点,但这不是一种好的(有效的)方法.深入分析(即仔细分析之前发生的关系)可能会发现这volatile是不必要的.例如,如果一个线程初始化了常量,然后THEN调用start()了所有使用它们的其他线程,那么(我认为)你可以逃避volatile没有其他同步.

但是......宣布常数final是更强大的方法2.


更新更新后的问题中的伪代码:

    伪代码版本是不正确的,即使它在其他任何地方都没有改变.问题是是否所有线程都能保证看到初始值.问题是内存模型不需要long_val由创建ThreadSafeClass实例的线程刷新.这意味着另一个线程在调用时可以看到默认的初始值(零)calculate().

    如果local_long被初始化synchronized块,伪代码将是正确的.

    如果long_valfinalvolatile, then the同步`块将不需要(至少为此目的).(出于不同的原因......)


1 - 基本上,您需要确保在"最终"生效之前没有其他线程使用常量字段.对于最终实例字段,这意味着在构造函数返回之前.对于最终的静态字段,这意味着在类初始化完成之前......当然注意到作为编译时常量的静态最终字段的处理方式不同.

2 - 我排除了使用反射来改变final字段的边缘情况.这是邪恶的,它使所有关于可见性的保证无效.只是不要这样做.

推荐阅读
臭小子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有