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ć?

Author: informatik01, 2012-02-18

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.
 22
Author: ahawtho,
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.

 0
Author: Edward,
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?

 0
Author: Xmw,
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