在"Effective Java"中,作者提到了这一点
while (!done) i++;
Run Code Online (Sandbox Code Playgroud)
可以通过HotSpot进行优化
if (!done) {
while (true) i++;
}
Run Code Online (Sandbox Code Playgroud)
我很困惑.变量done通常不是const,为什么编译器可以优化这种方式?
我读了一些关于提升和重新排序的内容,因此似乎Java VM可能会选择提升某些表达式.我还读到了在Javascript中提升函数声明的问题.
第一个问题: 有人可以确认在C,C++和Java中是否通常存在提升?或者它们都依赖于编译器/优化?
我读了很多示例C代码,它们总是在任何断言或边界条件之前将变量声明置于顶部.我认为在变量声明之前执行所有断言和边界情况会更快一些,因为函数可能只是终止.
主要问题: 变量声明必须始终在上下文中排在最前面吗?(这里有提升工作吗?)或者编译器是否通过首先检查这些独立的断言和边界情况(在无关变量声明之前)来自动优化代码?
这是一个相关的例子:
void MergeSort(struct node** headRef) {
struct node* a;
struct node* b;
if ((*headRef == NULL) || ((*headRef)->next == NULL)) {
return;
}
FrontBackSplit(*headRef, &a, &b);
MergeSort(&a);
MergeSort(&b);
*headRef = SortedMerge(a, b);
}
Run Code Online (Sandbox Code Playgroud)
如上所示,边界情况不依赖于变量"a"和"b".因此,将边界情况放在变量声明之上会使它稍快一些吗?
更新:
上面的例子并不像我希望的那样好,因为变量"a"和"b"只是声明,而不是在那里初始化.在我们确实需要使用它们之前,编译器会忽略声明.
我通过初始化检查了GNU GCC程序集的变量声明,程序集具有不同的执行顺序.编译器没有改变我对独立断言和边界情况的排序. 因此,重新排序这些断言和边界情况会改变程序集,从而改变机器运行它们的方式.
我认为差异是微不足道的,大多数人从不关心这一点.
在 C/C++ 中,我们必须在调用函数之前声明它们。在Javascript中有一个提升变量和函数。我找不到有关 Java 的信息。是否也有方法提升?
我阅读了一些关于易变性线程缓存的文章,发现它没有例子太简短,所以初学者很难理解.
请帮我理解下面的程序,
public class Test {
int a = 0;
public static void main(String[] args) {
final Test t = new Test();
new Thread(new Runnable(){
public void run() {
try {
Thread.sleep(3000);
} catch (Exception e) {}
t.a = 10;
System.out.println("now t.a == 10");
}
}).start();
new Thread(new Runnable(){
public void run() {
while(t.a == 0) {}
System.out.println("Loop done: " + t.a);
}
}).start();
}
}
Run Code Online (Sandbox Code Playgroud)
当我做a变量volatile和运行我的程序那么一段时间后停止,但是当我删除volatile到a变量,那么它的推移,我的程序不会停止.
我对volatile的了解是"当变量被声明为volatile时,线程将直接读/写到变量内存而不是从本地线程缓存读/写.如果没有声明volatile,那么可以看到实际值更新的延迟."
另外,根据我对刷新缓存副本的理解,我认为程序会在一段时间内停止但是为什么在上面的程序中它继续运行而不是更新.
那么什么时候Thread引用它的本地缓存开始引用主副本或者用主副本刷新它的值?
如果我理解错了,请纠正我.
请用一些小代码片段或链接向我解释.