Dlaczego HotSpot zoptymalizuje następujące elementy za pomocą podnoszenia?
W "efektywnej Javie" autor wspomniał, że
while (!done) i++;
Może być zoptymalizowany przez HotSpot do
if (!done) {
while (true) i++;
}
Jestem bardzo zdezorientowany. Zmienna {[2] } zazwyczaj nie jest const, dlaczego kompilator może w ten sposób zoptymalizować?
3 answers
Autor zakłada tam, że zmienna done
jest zmienną lokalną, która w modelu pamięci Java nie ma żadnych wymagań, aby wystawiać swoją wartość innym wątkom bez synchronizacji. Albo w inny sposób: wartość done
nie będzie zmieniana ani wyświetlana przez żaden kod inny niż pokazany tutaj.
W takim przypadku, ponieważ pętla nie zmienia wartości done
, jej wartość może być skutecznie ignorowana, a kompilator może podnieść ocenę tej zmiennej poza pętlą, uniemożliwiając jej ocenę w "gorącej" części pętli. To sprawia, że pętla działa szybciej, ponieważ musi wykonywać mniej pracy.
Działa to również w bardziej skomplikowanych wyrażeniach, takich jak długość tablicy:
int[] array = new int[10000];
for (int i = 0; i < array.length; ++i) {
array[i] = Random.nextInt();
}
W tym przypadku, naiwna implementacja oceniałaby długość tablicy 10 000 razy, ale ponieważ tablica zmiennych nigdy nie jest przypisana i długość tablicy nigdy się nie zmieni, ewaluacja może zmienić się na:
int[] array = new int[10000];
for (int i = 0, $l = array.length; i < $l; ++i) {
array[i] = Random.nextInt();
}
Inne stosuje się tu również optymalizacje niezwiązane z podnoszeniem.
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-17 11:21:46
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();
}
}
Powyższy kod znajduje się w efektywnym kodzie , równoważnym jest użycie {[2] } do dekoracji stopRequested
.
private static boolean stopRequested() {
return stopRequested;
}
Jeśli ta metoda pomija słowo kluczowe synchronized
, program nie działa dobrze.
Myślę, że ta zmiana powoduje podnoszenie, gdy metoda pomija słowo kluczowe synchronized
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-08 07:26:08
Jeśli dodasz System.out.println("i = " + i);
W pętli while. Podnoszenie nie będzie działać, co oznacza, że program zatrzymuje się zgodnie z oczekiwaniami. Metoda println jest Bezpieczna, więc jvm nie może zoptymalizować segmentu kodu?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-18 08:08:19