这个:
if (var) {
var = false;
}
Run Code Online (Sandbox Code Playgroud)
对此:
var = false;
Run Code Online (Sandbox Code Playgroud)
有速度差吗?
有几件事情发挥作用,对实际性能的最终影响是您需要根据用例来衡量的.我认为这是你发现的一种方法很多:
分支预测 - 如果var几乎总是假的,这就是代码所暗示的,分支预测器几乎总是正确的.如果该字段经常变化,那么这将成为一个经常被错误预测的分支并且将是昂贵的.
读取未命中 - 如果var主要是读取(并且读取很多),那么避免无故更改可以通过不使其所在的高速缓存行无效来帮助您的软件.如果你写它,每个读取它的核心(以及同一个缓存行上的任何内容)都需要获得一个新的副本来体验读取错过.这意味着为了使读取具有更一致的速度,上述方法可能值得变慢.
写入成本与读取成本 - 如果var是易失性的,那么它的写入是一个非常昂贵的LoadStore屏障.相比之下,读取volatile(一个LoadLoad屏障)是相当便宜的(对于经常使用且几乎没有改变的值的缓存命中).相比之下,这可以使分支非常便宜.
这是人们的优化,可以在JDK(IIRC)中找到示例,我假设您有理由考虑它.
第一个代码包含比较,因此您的编译器可能会生成一个类似于以下内容的java字节码:
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iload_1
3: ifeq 8
6: iconst_0
7: istore_1
8: return
Run Code Online (Sandbox Code Playgroud)
对于第二个代码,生成的字节码较短,因为缺少比较:
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_0
3: istore_1
4: return
Run Code Online (Sandbox Code Playgroud)
虚拟机在第一个示例中需要更多时间来执行8个命令,而在第二个示例中需要4个命令.虽然这种差异不应该高,但第二代码更清楚.
将代码放在一个简单的main方法中并编译该类.然后运行命令提示符并切换到java/bin目录.要反汇编你的课堂电话javap -c path/to/YourClass.class >> path/to/bytecode.txt.bytecode.txt将包含您的类的java字节码.