java最终变量和性能

时间:2015-05-29 08:18:19

标签: java multithreading performance

是不是很好,如果java代码过饱和了最终变量?我考虑性能。据我所知,最终变量是线程安全的。因此,对于最终变量的每个初始化,jvm必须在所有线程之间同步其值。如果我在每个我希望变量不可修改的情况下使用最终变量,它会达到性能吗?

我期待并担心最终变量会降低性能。

3 个答案:

答案 0 :(得分:6)

我明白你的观点。一般来说,具有final字段的类是线程安全的,因为您无法编写直接在运行时修改这些字段的代码。因此,没有任何其他线程可以意外地修改这种不可变类的实例。 现在,关于成本。没有特定的java字节码来读/写最终字段。此外,您可以通过Reflection,JNI调用,生成的字节码(除了“普通”构造函数路径)更改任何最终字段。这意味着最后的字段不是最终的,它们似乎只是一个编译时间限制,一种语法糖。但是, MAY 影响性能的最终字段有一个特定方面,因为JMM为它们定义了特定的语义(通常是专业成本,不是吗?):):http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5 它为包含最终字段的构造函数定义了合成同步操作“冻结操作”。该动作是“冻结动作 - 读取对创建对象的引用”HB边缘的一部分,它确实保证所有线程都能正确地看到初始化的最终字段。但我们看到,在现实生活中,冻结和非冻结构造函数之间没有任何显着差异:http://shipilev.net/blog/2014/all-fields-are-final/

因此,最重要的是,最终字段的成本与非最终字段的成本几乎相同。本地最终变量是一种纯粹的语法糖,并且与非最终本地人相比没有任何成本。

最后,如果你开发一个高性能/低延迟的应用程序,不要在它的主路径中使用不可变对象(不要一直分配内存),使用可变对象(带缓冲区,池)等等,因为通常即使一个空的构造函数花费大约30ns +次要GC也不是免费的+缓存局部性在密集内存(重新)分配的情况下是最差的...

答案 1 :(得分:2)

最终变量背后没有任何表现理由。您可以通过使用不可变对象来获得性能,因为在这种情况下,java可以避免GC在这些对象上运行。即使字段是最终字段,您也只是说您没有将指针的几个字节移动到此对象,它没有性能影响,因为您仍然可以修改此对象的字段。提高性能(通过减少GC开销)的唯一方法是尽可能使用不可变对象。但是你需要合理,不要以降低代码可读性为代价强迫所有东西变得不可变。

答案 2 :(得分:0)

最终变量没有性能问题。

如果要在多线程环境中使用变量而不是使用最终变量,请使用Volatile变量。

易失性变量是线程安全的。 Java中的volatile关键字保证volatile变量的值总是从主内存中读取,而不是从Thread的本地缓存中读取。