Kiedy dokładnie używasz słowa kluczowego volatile w Javie? [duplikat]

Author: Ravindra babu, 2010-08-15

1 answers

Zasadniczo używasz go, gdy chcesz, aby zmienna członkowska była dostępna przez wiele wątków, ale nie potrzebujesz atomiczności złożonej (nie jesteś pewien, czy jest to właściwa terminologia).

class BadExample {
    private volatile int counter;

    public void hit(){
        /* This operation is in fact two operations:
         * 1) int tmp = this.counter;
         * 2) this.counter = tmp + 1;
         * and is thus broken (counter becomes fewer
         * than the accurate amount).
         */
        counter++;
    }
}

Powyższy przykład jest złym przykładem, ponieważ potrzebujesz atomiczności złożonej.

 class BadExampleFixed {
    private int counter;

    public synchronized void hit(){
        /*
         * Only one thread performs action (1), (2) at a time
         * "atomically", in the sense that other threads can not 
         * observe the intermediate state between (1) and (2).
         * Therefore, the counter will be accurate.
         */
        counter++;
    }
}

Teraz do poprawnego przykładu:

 class GoodExample {
    private static volatile int temperature;

    //Called by some other thread than main
    public static void todaysTemperature(int temp){
        // This operation is a single operation, so you 
        // do not need compound atomicity
        temperature = temp;
    }

    public static void main(String[] args) throws Exception{
        while(true){
           Thread.sleep(2000);
           System.out.println("Today's temperature is "+temperature);
        }
    }
}

Teraz, dlaczego nie możesz po prostu użyć private static int temperature? Faktycznie możesz (w tym sensie, że twój program nie wybuchnie czy coś), ale zmiana na temperature przez drugą wątek może, ale nie musi być "widoczny" dla głównego wątku.

Zasadniczo oznacza to, że jest nawet możliwe, że Twoja aplikacja. zapisuje Today's temperature is 0 na zawsze, jeśli nie używasz volatile (w praktyce wartość staje się ostatecznie widoczna. Nie powinieneś jednak ryzykować, że nie użyjesz lotnych, gdy jest to konieczne, ponieważ może to prowadzić do paskudnych błędów (spowodowanych przez całkowicie zbudowane obiekty itp.).

Jeśli umieścisz volatile słowo kluczowe na czymś, co nie jest potrzebne volatile, nie wpłynie to na twoje poprawność kodu (tzn. zachowanie nie ulegnie zmianie). Jeśli chodzi o wydajność, będzie to zależało od implementacji JVM. Teoretycznie może dojść do niewielkiego pogorszenia wydajności, ponieważ kompilator nie może dokonać zmiany kolejności optymalizacji, musi unieważnić pamięć podręczną procesora itp., ale z drugiej strony kompilator może udowodnić, że pole nie może być dostępne przez wiele wątków i całkowicie usunąć efekt słowa kluczowego volatile i skompilować go do identycznych instrukcji.

EDIT:
Odpowiedź na ten komentarz:

Ok, ale dlaczego nie możemy dziś zsynchronizować temperatury i utworzyć zsynchronizowany getter dla temperatury?

Można i będzie zachowywać się poprawnie. Wszystko, co można z volatile można zrobić z synchronized, ale nie odwrotnie. Istnieją dwa powody, dla których możesz wybrać volatile, jeśli możesz:

  1. mniej podatne na błędy: zależy to od kontekstu, ale w wielu przypadkach użycie volatile jest mniej podatne na błędy podatne na błędy współbieżności, takie jak blokowanie podczas trzymania blokady, deadlocks itp.
  2. bardziej wydajny: w większości implementacji JVM, volatile może mieć znacznie wyższą przepustowość i lepsze opóźnienia. Jednak w większości zastosowań różnica jest zbyt mała, aby mieć znaczenie.
 110
Author: Enno Shioji,
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
2014-07-22 07:11:00