Чтение Эффективная Java, автор упомянул, что
while(!done) i++;
можно оптимизировать по горячей точке в
if (!done) {
while(true) i++
}
Я очень смущен. сделано обычно не const, почему компилятор может оптимизировать этот путь?
Чтение Эффективная Java, автор упомянул, что
while(!done) i++;
можно оптимизировать по горячей точке в
if (!done) {
while(true) i++
}
Я очень смущен. сделано обычно не const, почему компилятор может оптимизировать этот путь?
Автор предполагает, что переменная done
является локальной переменной, которая не имеет каких-либо требований в модели памяти Java, чтобы выставлять ее значение для других потоков без примитивов синхронизации. Или сказал другой способ: значение done
не будет изменено или просмотрено каким-либо другим кодом, кроме показанного здесь.
В этом случае, поскольку цикл не меняет значение done
, его значение может быть эффективно проигнорировано, и компилятор может поднять оценку этой переменной за пределы цикла, не позволяя ей оцениваться в "горячей" части цикла. Это заставляет цикл работать быстрее, потому что он должен делать меньше работы.
Это также работает в более сложных выражениях, таких как длина массива:
int[] array = new int[10000];
for (int i = 0; i < array.length; ++i) {
array[i] = Random.nextInt();
}
В этом случае наивная реализация будет оценивать длину массива 10 000 раз, но поскольку массив переменных никогда не назначается и длина массива никогда не изменится, оценка может измениться на:
int[] array = new int[10000];
for (int i = 0, $l = array.length; i < $l; ++i) {
array[i] = Random.nextInt();
}
Другие оптимизации также применяются здесь, не связанные с подъемом.
Надеюсь, что это поможет.
Если вы добавите System.out.println("i = " + i);
в цикл while. Подъем не будет работать, что означает, что программа останавливается, как ожидалось. Метод println является потокобезопасным, так что jvm не может оптимизировать сегмент кода?
public class StopThread {
private static boolean stopRequested;
private static synchronized void requestStop() {
stopRequested = true;
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested())
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
приведенный выше код имеет право в эффективном коде, он эквивалентен использованию volatile
для украшения stopRequested
.
private static boolean stopRequested() {
return stopRequested;
}
Если этот метод опускает ключевое слово synchronized
, эта программа не работает.
Я думаю, что это изменение вызывает hoisting, когда метод опускает ключевое слово synchronized
.