web-dev-qa-db-fra.com

Pourquoi les variables locales sont-elles sécurisées dans Java

Je lisais le multi-threading dans Java et je tombe sur cette

Les variables locales sont thread-safe en Java.

Depuis lors, je me suis demandé pourquoi et comment les variables locales sont thread-safe.

Quelqu'un peut-il me faire savoir s'il vous plaît.

84
Anand

Lorsque vous créez un thread, sa propre pile est créée. Deux threads auront deux piles et un thread ne partage jamais sa pile avec un autre thread.

La mémoire dans la pile sera allouée à toutes les variables locales définies dans votre programme (comme le dit Jatin, mémoire signifie ici, valeur de référence pour les objets et valeur pour les types primitifs) (chaque appel de méthode par un thread crée un cadre de pile sur sa propre pile). Dès que l'exécution de la méthode est terminée par ce thread, le cadre de pile sera supprimé.

Il y a une excellente conférence de professeur de Stanford sur youtube qui peut vous aider à comprendre ce concept.

94
kosa

Les variables locales sont stockées dans la pile de chaque thread. Cela signifie que les variables locales ne sont jamais partagées entre les threads. Cela signifie également que toutes les variables primitives locales sont thread-safe.

public void someMethod(){

   long threadSafeInt = 0;

   threadSafeInt++;
}

Les références locales aux objets sont un peu différentes. La référence elle-même n'est pas partagée. L'objet référencé n'est cependant pas stocké dans la pile locale de chaque thread. Tous les objets sont stockés dans le segment de mémoire partagé. Si un objet créé localement n'échappe jamais à la méthode dans laquelle il a été créé, il est thread-safe. En fait, vous pouvez également le transmettre à d'autres méthodes et objets à condition qu'aucune de ces méthodes ou objets ne rende l'objet transmis disponible à d'autres threads.

17
Renjith

Pensez à des méthodes telles que les définitions de fonctionnalité. Lorsque deux threads exécutent la même méthode, ils ne sont aucunement liés. Ils créeront chacun leur propre version de chaque variable locale et seront incapables d'interagir les uns avec les autres.

Si les variables ne sont pas locales (comme les variables d'instance définies en dehors d'une méthode au niveau de la classe), elles sont alors attachées à l'instance (et non à une seule exécution de la méthode). Dans ce cas, deux threads exécutant la même méthode voient la même variable, ce qui n'est pas thread-safe.

Considérons ces deux cas:

public class NotThreadsafe {
    int x = 0;
    public int incrementX() {
        x++;
        return x;
    }
}

public class Threadsafe {
    public int getTwoTimesTwo() {
        int x = 1;
        x++;
        return x*x;
    }
}

Dans le premier, deux threads s'exécutant sur la même instance de NotThreadsafe verront le même x. Cela pourrait être dangereux, car les discussions tentent de changer x! Dans le second cas, deux threads exécutés sur la même instance de Threadsafe verront des variables totalement différentes et ne pourront s’affecter mutuellement.

14
Cory Kendall

En plus des autres réponses telles que celle de Nambari.

Je voudrais souligner que vous pouvez utiliser une variable locale dans une méthode de type anonyme:

Cette méthode peut être appelée dans d'autres threads, ce qui peut compromettre la sécurité des threads. Java oblige toutes les variables locales utilisées dans des types anonymes à être déclarées comme finales.

Considérez ce code illégal:

public void nonCompilableMethod() {
    int i=0;
    for(int t=0; t<100; t++)
    {
      new Thread(new Runnable() {
                    public void run() {
                      i++; //compile error, i must be final:
                      //Cannot refer to a non-final variable i inside an
                      //inner class defined in a different method
                    }
       }).start();
     }
  }

Si Java permettait cela (comme C # le fait avec des "fermetures"), une variable locale ne serait plus threadsafe dans toutes les circonstances. Dans ce cas, la valeur de i à la fin de tous les threads n'est pas garantie d'être 100.

6
weston

Chaque appel de méthode a ses propres variables locales et, évidemment, un appel de méthode se produit dans un seul thread. Une variable qui n'est mise à jour que par un seul thread est intrinsèquement thread-safe.

Cependant, gardez un œil attentif sur le sens exact de ceci: seulement les écritures dans la variable elle-même sont thread-safe; appelant des méthodes sur l'objet auquel il fait référence n'est pas intrinsèquement thread-safe. Il en va de même pour la mise à jour directe des variables d'objet.

5
Marko Topolnik

Le fil aura sa propre pile. Deux threads auront deux piles et un thread ne partage jamais sa pile avec un autre thread. Les variables locales sont stockées dans la pile de chaque thread. Cela signifie que les variables locales ne sont jamais partagées entre les threads.

5
Sudhir Murkute

Il existe essentiellement quatre types de stockage dans Java pour stocker les informations de classe et les données:

zone de méthode, tas, pile Java, PC

ainsi, la zone Method et Heap sont partagés par tous les threads, mais chaque thread possède son propre Java Stack et PC, qui n'est partagé par aucun autre Threads.

Chaque méthode de Java correspond au cadre de pile. Ainsi, lorsqu'une méthode est appelée par un fil, ce cadre de pile est chargé sur son Java Stack.All le local Les variables présentes dans ce cadre de pile et la pile d'opérande associée ne sont pas partagées par d'autres. Le PC disposera des informations sur l'instruction suivante à exécuter dans le code d'octet de la méthode, de sorte que toutes les variables locales sont THREAD SAFE.

@Weston a également donné une bonne réponse.

3
Prashant

J'aime l'explication de jenkov

La pile de threads contient toutes les variables locales pour chaque méthode en cours d'exécution (toutes les méthodes de la pile d'appels). Un thread ne peut accéder qu'à sa propre pile de threads. Les variables locales créées par un thread sont invisibles pour tous les threads autres que le thread qui l'a créé. Même si deux threads exécutent exactement le même code, ils créeront toujours les variables locales de ce code dans leurs propres piles de threads. Ainsi, chaque thread a sa propre version de chaque variable locale.

Toutes les variables locales de types primitifs (boolean, octet, short, char, int, long, float, double) sont entièrement stockées sur la pile de threads et ne sont donc pas visibles par les autres threads. Un thread peut transmettre une copie d'une variable pritimive à un autre thread, mais il ne peut pas partager la variable locale primitive elle-même.

Le tas contient tous les objets créés dans votre Java, quel que soit le thread ayant créé l’objet, y compris les versions d’objet des types primitifs (par exemple, Byte, Integer, Long, etc.), peu importe si un objet a été créé et affecté à une variable locale, ou créé en tant que variable membre d'un autre objet, l'objet est toujours stocké sur le tas.

enter image description here Une variable locale peut être de type primitif , auquel cas elle est totalement conservée sur le thread pile .

Une variable locale peut également être une référence à un objet. Dans ce cas, la référence (la variable locale) est stockée sur la pile de threads , mais l’objet lui-même s'il est stocké sur le tas .

Veuillez lire la suite - http://tutorials.jenkov.com/Java-concurrency/Java-memory-model.html

2
yoAlex5